From 481513cfc3e12c82fe2e3735dc04c1c11ff05ae9 Mon Sep 17 00:00:00 2001 From: SKairinos Date: Fri, 31 May 2024 11:32:14 +0000 Subject: [PATCH 1/2] fix: rtk helpers --- src/helpers/rtkQuery.ts | 263 ++++++++++++++++++++++++++-------------- 1 file changed, 172 insertions(+), 91 deletions(-) diff --git a/src/helpers/rtkQuery.ts b/src/helpers/rtkQuery.ts index 610a9636..351934a0 100644 --- a/src/helpers/rtkQuery.ts +++ b/src/helpers/rtkQuery.ts @@ -1,3 +1,5 @@ +import type { FetchBaseQueryError } from "@reduxjs/toolkit/query"; + // ----------------------------------------------------------------------------- // Model Types // ----------------------------------------------------------------------------- @@ -5,48 +7,31 @@ // The fields of a model. export type Fields = Record; +export type TagId = string | number; + +export type Tag = { + type: Type; + id: TagId; +}; + /** * A data model. - * ID: The type of ID. - * ReadAndWrite: The fields that can both be read from and written to. - * ReadOnly: The fields that can only be read from. 'id' is a mandatory - * read-only field. - * WriteOnly: The fields that can only be written to. + * Id: The type of Id. + * Data: The data fields. */ -export type Model< - ID, - ReadAndWrite extends Fields = Fields, - ReadOnly extends Fields = Fields, - WriteOnly extends Fields = Fields -> = ReadAndWrite & { - _readOnly: ReadOnly & { id: ID; }; - _writeOnly: WriteOnly; -}; +export type Model = { + id: Id; +} & Omit; -// Gets the type of a model's ID. -export type ID> = M['_readOnly']['id']; +export type Result, MFields extends keyof M = "id"> = Pick< + M, + "id" | MFields +>; -// Gets the types of a model's readable fields. -export type ReadFields> = - Omit & M['_readOnly']; - -// Gets the types of a model's writeable fields. -export type WriteFields> = - Omit & M['_writeOnly']; - -// Gets the types of a model's readable and writeable fields. -export type ReadAndWriteFields> = - Omit & M['_readOnly'] & M['_writeOnly']; - -// An array of tags with ID's. -export type TagArray< - Type extends string, - M extends Model, - LookupField extends keyof ReadFields = 'id' -> = Array<{ - type: Type; - id: ReadFields[LookupField]; -}>; +export type Arg, MFields extends keyof M> = Pick< + M, + MFields +>; // ----------------------------------------------------------------------------- // CRUD Types @@ -55,103 +40,199 @@ export type TagArray< // Create -export type CreateResult> = ReadFields; +export type CreateResult< + M extends Model, + MFields extends keyof M = "id", +> = Result; -export type CreateArg> = WriteFields; +export type CreateArg< + M extends Model, + MFields extends keyof Omit, +> = Arg; -export type BulkCreateResult> = Array>; +export type BulkCreateResult< + M extends Model, + MFields extends keyof M = "id", + ExtraFields extends Fields = Fields, +> = Array & ExtraFields>; -export interface BulkCreateArg> { - data: Array>; -} +export type BulkCreateArg< + M extends Model, + MFields extends keyof Omit, + ExtraFields extends Fields = Fields, +> = Array & ExtraFields>; // Read -export type RetrieveResult> = ReadFields; - -export type RetrieveArg< +export type RetrieveResult< M extends Model, - LookupField extends keyof ReadAndWriteFields = 'id' -> = Pick, LookupField>; + MFields extends keyof M = "id", +> = Result; + +export type RetrieveArg> = M["id"]; -export interface ListResult> { +export interface ListResult< + M extends Model, + MFields extends keyof M = "id", + ExtraFields extends Fields = Fields, +> { count: number; offset: number; limit: number; maxLimit: number; - data: Array>; + data: Array & ExtraFields>; } -export type ListArg = - null | Partial; +export type ListArg = { + limit: number; + offset: number; +} & Partial>; // Update -export type UpdateResult> = ReadFields; +export type UpdateResult< + M extends Model, + MFields extends keyof M = "id", +> = Result; export type UpdateArg< M extends Model, - LookupField extends keyof ReadAndWriteFields = 'id' -> = Pick, LookupField> & Partial>; + MFields extends keyof Omit, + ExtraFields extends Fields = Fields, +> = [M["id"], Arg & ExtraFields]; -export type BulkUpdateResult> = Array>; +export type BulkUpdateResult< + M extends Model, + MFields extends keyof M = "id", + ExtraFields extends Fields = Fields, +> = Array & ExtraFields>; -export interface BulkUpdateArg< +export type BulkUpdateArg< M extends Model, - LookupField extends keyof ReadAndWriteFields = 'id' -> { - data: Array>; -} + MFields extends keyof Omit, + ExtraFields extends Fields = Fields, +> = Record & ExtraFields>; + +export type PartialUpdateResult< + M extends Model, + MFields extends keyof M = "id", +> = Result; + +export type PartialUpdateArg< + M extends Model, + MFields extends keyof Omit, + ExtraFields extends Fields = Fields, +> = [M["id"], Partial & ExtraFields>]; + +export type BulkPartialUpdateResult< + M extends Model, + MFields extends keyof M = "id", + ExtraFields extends Fields = Fields, +> = Array & ExtraFields>; + +export type BulkPartialUpdateArg< + M extends Model, + MFields extends keyof Omit, + ExtraFields extends Fields = Fields, +> = Record & ExtraFields>>; // Delete export type DestroyResult = null; -export type DestroyArg< - M extends Model, - LookupField extends keyof ReadAndWriteFields = 'id' -> = Pick, LookupField>; +export type DestroyArg> = M["id"]; export type BulkDestroyResult = null; -export interface BulkDestroyArg< - M extends Model, - LookupField extends keyof ReadAndWriteFields = 'id' -> { - LookupField: Array[LookupField]>; -} +export type BulkDestroyArg> = Array; // ----------------------------------------------------------------------------- // Functions // ----------------------------------------------------------------------------- -export function searchParamsToString(arg: ListArg): string { - if (arg !== null) { - const searchParams = Object.entries(arg) +export function buildUrl( + url: string, + params: { + search?: Fields; + url?: Fields; + } +): string { + if (params.url) { + Object.entries(params.url).forEach(([key, value]) => { + url = url.replace(`<${key}>`, String(value)); + }); + } + + if (params.search) { + const searchParams = Object.entries(params.search) .filter(([_, value]) => value !== undefined) .map(([key, value]) => [key, String(value)]); if (searchParams.length !== 0) { - return `?${new URLSearchParams(searchParams).toString()}`; + url += `?${new URLSearchParams(searchParams).toString()}`; } } - return ''; + return url; } -export function tagData< - Type extends string, - M extends Model, - LookupField extends keyof ReadFields = 'id' ->( - result: ListResult | BulkCreateResult, - type: Type, - lookupField: LookupField = 'id' as LookupField -): TagArray { - const data = 'data' in result ? result.data : result; - - return data.map((result) => ({ - type, - id: result[lookupField] - })) as TagArray; +export function isTagId(value: unknown): boolean { + return typeof value === "number" || typeof value === "string"; +} + +export function tagData>( + type: Type +): ( + result: + | Result + | Array> + | ListResult + | null + | undefined, + error: FetchBaseQueryError | undefined, + arg: + | Arg + | Array> + | [M["id"], Arg] + | Record + | ListArg + | Array + | string + | number + | undefined +) => Array> { + return (result, error, arg) => { + if (!error) { + if (arg) { + if (isTagId(arg)) return [{ type, id: arg as TagId }]; + + if (Array.isArray(arg) && arg.length > 0) { + if (isTagId(arg[0])) { + if (arg.length === 2 && !isTagId(arg[1])) { + return [{ type, id: (arg as [M["id"], Arg])[0] }]; + } + + return (arg as Array).map((id) => ({ type, id })); + } + } + } + + if (result) { + if ("id" in result) { + return [{ type, id: result["id"] as TagId }]; + } + + if (Array.isArray(result)) { + return result.map((result) => ({ type, id: result["id"] as TagId })); + } + + return (result as ListResult).data.map((result) => ({ + type, + id: result["id"] as TagId, + })); + } + } + + return []; + }; } From 01d60dbbd4ee57682427e69aec24b27bbd9ced1e Mon Sep 17 00:00:00 2001 From: SKairinos Date: Fri, 31 May 2024 12:00:47 +0000 Subject: [PATCH 2/2] fix: type --- src/helpers/rtkQuery.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/rtkQuery.ts b/src/helpers/rtkQuery.ts index 351934a0..bc6fa7e5 100644 --- a/src/helpers/rtkQuery.ts +++ b/src/helpers/rtkQuery.ts @@ -194,7 +194,7 @@ export function tagData>( | Arg | Array> | [M["id"], Arg] - | Record + | Record> | ListArg | Array | string