Skip to content

Commit

Permalink
fix(jsonapi): fix types of relationships in create / update payloads #56
Browse files Browse the repository at this point in the history
  • Loading branch information
chfoidl committed Aug 31, 2023
1 parent 5352136 commit 8de8a48
Showing 1 changed file with 52 additions and 50 deletions.
102 changes: 52 additions & 50 deletions packages/jsonapi/src/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export interface JsonApiResource {
* }
* ```
*/
export interface JsonApiResources {}
export interface JsonApiResources { }

/**
* This interface defines the internal jsonapi resources.
Expand Down Expand Up @@ -113,6 +113,11 @@ export interface JsonApiIndex extends Response<[]> {
};
}

export interface RelationshipLinkage<T extends string> {
type: T;
id: string;
}

/**
* Utility types.
*/
Expand All @@ -129,35 +134,35 @@ type ExtractArrayElementType<T> = T extends Array<infer U> ? U : never;

type DeriveSimpleJsonApiResourceUnion<T> =
T extends infer U extends JsonApiResource
? DeriveSimpleJsonApiResource<U>
: never;
? DeriveSimpleJsonApiResource<U>
: never;

export type DeriveSimpleJsonApiResource<TResource extends JsonApiResource> = {
id: TResource["id"];
type: TResource["type"];
resourceIdObjMeta: {
[key in keyof TResource["meta"]]: TResource["meta"][key] extends Meta[0]
? TResource["meta"][key]
: never;
? TResource["meta"][key]
: never;
};
links: {
[key in keyof TResource["links"]]: TResource["links"][key] extends Link
? TResource["links"][key]
: never;
? TResource["links"][key]
: never;
};
} & {
[key in keyof TResource["attributes"]]: TResource["attributes"][key] extends Attributes[0]
[key in keyof TResource["attributes"]]: TResource["attributes"][key] extends Attributes[0]
? TResource["attributes"][key]
: never;
} & {
[key in keyof TResource["relationships"]]: TResource["relationships"][key] extends JsonApiResource
} & {
[key in keyof TResource["relationships"]]: TResource["relationships"][key] extends JsonApiResource
? DeriveSimpleJsonApiResourceUnion<TResource["relationships"][key]>
: TResource["relationships"][key] extends JsonApiResource[]
? DeriveSimpleJsonApiResourceUnion<
ExtractArrayElementType<TResource["relationships"][key]>
>[]
ExtractArrayElementType<TResource["relationships"][key]>
>[]
: never;
};
};

/**
* The following types are used to derive a ts-json-api resource
Expand All @@ -173,32 +178,38 @@ export type DeriveResourceObject<TResource extends JsonApiResource> = {
id: TResource["id"];
attributes: {
[key in keyof TResource["attributes"]]: TResource["attributes"][key] extends Attributes[0]
? TResource["attributes"][key]
: never;
? TResource["attributes"][key]
: never;
};
meta: {
[key in keyof TResource["meta"]]: TResource["meta"][key] extends Meta[0]
? TResource["meta"][key]
: never;
? TResource["meta"][key]
: never;
};
links: {
[key in keyof TResource["links"]]: TResource["links"][key] extends Link
? TResource["links"][key]
: never;
? TResource["links"][key]
: never;
};
relationships: {
[key in keyof TResource["relationships"]]: TResource["relationships"][key] extends JsonApiResource
? Relationship<DeriveResourceObject<TResource["relationships"][key]>>
: TResource["relationships"][key] extends JsonApiResource[]
? Relationship<
DeriveResourceObjectUnion<
ExtractArrayElementType<TResource["relationships"][key]>
>[]
>
: never;
? Relationship<DeriveResourceObject<TResource["relationships"][key]>>
: TResource["relationships"][key] extends JsonApiResource[]
? Relationship<
DeriveResourceObjectUnion<
ExtractArrayElementType<TResource["relationships"][key]>
>[]
>
: never;
};
};

type ResourceRelationshipLinkage<T> = T extends JsonApiResource
? RelationshipLinkage<T["type"]>
: T extends JsonApiResource[]
? RelationshipLinkage<ExtractArrayElementType<T>["type"]>[]
: never;

/**
* Creates a simple json api resource from a resource object.
*
Expand All @@ -211,27 +222,18 @@ export type SimpleFromResourceObject<T> = T extends DeriveResourceObject<
: T extends DeriveResourceObject<infer TResource>[]
? DeriveSimpleJsonApiResource<TResource>[]
: never;

/**
* Extract the create payload type from a resource object.
*/
type ResourceCreatePayload<
R extends JsonApiResource,
TResourceObject extends DeriveResourceObject<R> = DeriveResourceObject<R>,
> = {
id?: TResourceObject["id"];
type?: TResourceObject["type"];
attributes?: Partial<TResourceObject["attributes"]>;
relationships?: Partial<TResourceObject["relationships"]>;
};
/**
* Extract the update payload type from a resource object.
*/
type ResourceUpdatePayload<R extends JsonApiResource> = object & {
type ResourceCreateUpdatePayload<R extends JsonApiResource> = object & {
id?: R["id"];
type?: R["type"];
attributes?: Partial<R["attributes"]>;
relationships?: Partial<R["relationships"]>;
relationships?: Partial<{
[key in keyof R["relationships"]]: {
data: ResourceRelationshipLinkage<R["relationships"][key]>;
};
}>;
};

export type ResourceResponse<
Expand All @@ -246,8 +248,8 @@ export type ResourceResult<
TReturnSimple extends boolean,
> = Result<
TReturnSimple extends true
? DeriveSimpleJsonApiResource<TResource>
: Response<DeriveResourceObject<TResource>>,
? DeriveSimpleJsonApiResource<TResource>
: Response<DeriveResourceObject<TResource>>,
DrupalkitJsonApiError
>;

Expand All @@ -258,10 +260,10 @@ export type ResourceResult<
*/
export type RemoveIndex<T> = {
[key in keyof T as string extends key
? never
: number extends key
? never
: key]: T[key];
? never
: number extends key
? never
: key]: T[key];
};

/**
Expand All @@ -279,12 +281,12 @@ export type ReadSingleParameters = ReadParameters & {
export type ReadManyParameters = ReadParameters;

export type CreateParameters<Resource extends JsonApiResource> = {
payload: ResourceCreatePayload<Resource>;
payload: ResourceCreateUpdatePayload<Resource>;
};

export type UpdateParameters<Resource extends JsonApiResource> = {
uuid: string;
payload: ResourceUpdatePayload<Resource>;
payload: ResourceCreateUpdatePayload<Resource>;
};

export type DeleteParameters = {
Expand Down

0 comments on commit 8de8a48

Please sign in to comment.