Skip to content

Commit

Permalink
fix api caching
Browse files Browse the repository at this point in the history
  • Loading branch information
SKairinos committed Aug 15, 2024
1 parent 2041787 commit 6868154
Showing 1 changed file with 53 additions and 21 deletions.
74 changes: 53 additions & 21 deletions src/utils/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ import type { Optional, Required } from "./general"
// The fields of a model.
export type Fields = Record<string, unknown>

export type TagId = string | number

export interface Tag<Type extends string> {
type: Type
id: TagId
id: string
}

export type ModelId = string | number

/**
* A data model.
* Id: The type of Id.
* Data: The data fields.
*/
export type Model<Id extends TagId, MFields extends Fields = Fields> = {
export type Model<Id extends ModelId, MFields extends Fields = Fields> = {
id: Id
} & Omit<MFields, "id">

Expand Down Expand Up @@ -187,13 +187,23 @@ export function buildUrl(
return url
}

export function isTagId(value: unknown): boolean {
export function isModelId(value: unknown): boolean {
return typeof value === "number" || typeof value === "string"
}

export function listTag<Type extends string>(type: Type): Tag<Type> {
return { type, id: "LIST" }
}

export type TagDataOptions = Partial<{
includeListTag: boolean
argKeysAreIds: boolean
id: string
}>

export function tagData<Type extends string, M extends Model<any>>(
type: Type,
id: string = "id",
options?: TagDataOptions,
): (
result:
| Result<M, any>
Expand All @@ -205,43 +215,65 @@ export function tagData<Type extends string, M extends Model<any>>(
arg:
| Arg<M, any>
| Array<Arg<M, any>>
| [M["id"], Arg<M, any>]
| Record<M["id"], Arg<M, any>>
| ListArg<any>
| Array<M["id"]>
| string
| number
| undefined,
) => Array<Tag<Type>> {
const {
includeListTag = false,
argKeysAreIds = false,
id = "id",
} = options || {}

function tags(
ids: ModelId[],
list: boolean = includeListTag,
): Array<Tag<Type>> {
const tags = ids.map(id => ({ type, id: String(id) }))
if (list) tags.push(listTag(type))
return tags
}

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<M, any>])[0] }]
}
// The argument is an ID.
if (isModelId(arg)) return tags([arg as ModelId])

return (arg as Array<M["id"]>).map(id => ({ type, id }))
// The argument is an array of IDs.
if (Array.isArray(arg)) {
if (arg.length && isModelId(arg[0])) {
return tags(arg as Array<M["id"]>)
}
}
// The argument is an object that contains the id field.
else if (typeof arg === "object" && argKeysAreIds) {
return tags(Object.keys(arg as Record<M["id"], any>))
}
}

if (result) {
// The result is a model that contains the id field.
if (id in result) {
return [{ type, id: (result as Result<M, any>)[id] as TagId }]
return tags([(result as Result<M, any>)[id] as ModelId])
}

// The result is an array of models that contain the id field.
if (Array.isArray(result)) {
return result.map(result => ({ type, id: result[id] as TagId }))
return tags(result.map(result => result[id] as ModelId))
}

return (result as ListResult<M, any>).data.map(result => ({
type,
id: result[id] as TagId,
}))
// The result is a list that contains an array of models that contain
// the id field.
return tags(
(result as ListResult<M, any>).data.map(
result => result[id] as ModelId,
),
true,
)
}
}

Expand Down

0 comments on commit 6868154

Please sign in to comment.