{"version":3,"file":"response.mjs","names":[],"sources":["../src/response.ts"],"sourcesContent":["import { hasText } from '@shware/utils';\nimport { _default, coerce, int, maximum, minimum, object, optional, string } from 'zod/mini';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Empty = {};\nexport type EntityId = string | number;\nexport type Entity = { id: EntityId };\n\nexport type Response<T = never> = { data: T };\n\nexport type InitParams = { limit: number; parent?: string };\nexport type NextParams = { limit: number; parent?: string; next: string };\nexport type PrevParams = { limit: number; parent?: string; prev: string };\nexport type PageParams = { limit: number; prev?: string; next?: string };\nexport type ParentPageParams = { limit: number; parent: string; prev?: string; next?: string };\nexport type Page<T = never> = { data: T[]; paging: { next?: string; prev?: string } };\n\nexport function pageParamsSchema(max = 100, defaultLimit = 20) {\n  return object({\n    limit: _default(coerce.number().check(int(), minimum(1), maximum(max)), defaultLimit),\n    prev: optional(string()),\n    next: optional(string()),\n  });\n}\n\nexport const Cursor = {\n  of(\n    prev: bigint | number | string | undefined,\n    next: bigint | number | string | undefined\n  ): Page['paging'] {\n    return {\n      prev: prev ? this.encode(prev) : undefined,\n      next: next ? this.encode(next) : undefined,\n    };\n  },\n  empty(): Page['paging'] {\n    return { prev: undefined, next: undefined };\n  },\n  encode(id: bigint | number | string | undefined): string | undefined {\n    if (!id) return undefined;\n    return Buffer.from(id.toString(), 'utf-8').toString('base64');\n  },\n  decode<T extends 'bigint' | 'number' | 'string' = 'bigint'>(\n    token: string,\n    type: T = 'bigint' as T\n  ): T extends 'bigint' ? bigint : T extends 'number' ? number : string {\n    const value = Buffer.from(token, 'base64').toString('utf-8');\n    if (type === 'bigint')\n      return BigInt(value) as T extends 'bigint' ? bigint : T extends 'number' ? number : string;\n    if (type === 'number')\n      return Number(value) as T extends 'bigint' ? bigint : T extends 'number' ? number : string;\n    return value as T extends 'bigint' ? bigint : T extends 'number' ? number : string;\n  },\n};\n\nexport const initialPageParam: Page['paging'] = {};\n\nexport function getPreviousPageParam<T = never>(first: Page<T>): Page['paging'] | null {\n  return hasText(first.paging.prev) ? { prev: first.paging.prev } : null;\n}\n\nexport function getNextPageParam<T = never>(last: Page<T>): Page['paging'] | null {\n  return hasText(last.paging.next) ? { next: last.paging.next } : null;\n}\n\nexport type InfinitePageData<T> = {\n  pages: Array<Page<T>>;\n  pageParams: Array<Page['paging']>;\n};\n\nexport const Pages = {\n  flatten<T>(data: InfinitePageData<T>): T[] {\n    return data.pages.flatMap((page) => page.data);\n  },\n  dedupe<T extends Entity>(data: InfinitePageData<T>): T[] {\n    const seen = new Set<EntityId>();\n    const result: T[] = [];\n    for (const page of data.pages) {\n      for (const item of page.data) {\n        if (!seen.has(item.id)) {\n          seen.add(item.id);\n          result.push(item);\n        }\n      }\n    }\n    return result;\n  },\n  prepend<T>(item: T) {\n    return (data: InfinitePageData<T> | undefined): InfinitePageData<T> | undefined => {\n      if (!data) return data;\n      const first = data.pages.at(0);\n      const rest = data.pages.slice(1);\n      if (!first) return { ...data, pages: [{ data: [item], paging: {} }] };\n      return { ...data, pages: [{ ...first, data: [item, ...first.data] }, ...rest] };\n    };\n  },\n  append<T>(item: T) {\n    return (data: InfinitePageData<T> | undefined): InfinitePageData<T> | undefined => {\n      if (!data) return data;\n      const pages = data.pages;\n      const last = pages.at(-1);\n      if (!last) return { ...data, pages: [{ data: [item], paging: {} }] };\n      return { ...data, pages: [...pages.slice(0, -1), { ...last, data: [...last.data, item] }] };\n    };\n  },\n  update<T>(updater: T, predicate: (item: T) => boolean) {\n    return (data: InfinitePageData<T> | undefined): InfinitePageData<T> | undefined => {\n      if (!data) return data;\n      return {\n        ...data,\n        pages: data.pages.map((page) => ({\n          ...page,\n          data: page.data.map((item) => (predicate(item) ? updater : item)),\n        })),\n      };\n    };\n  },\n  updateById<T extends Entity>(updated: T) {\n    return this.update<T>(updated, (item) => item.id === updated.id);\n  },\n  remove<T>(predicate: (item: T) => boolean) {\n    return (data: InfinitePageData<T> | undefined): InfinitePageData<T> | undefined => {\n      if (!data) return data;\n      return {\n        ...data,\n        pages: data.pages.map((page) => ({\n          ...page,\n          data: page.data.filter((item) => !predicate(item)),\n        })),\n      };\n    };\n  },\n  removeById<T extends Entity>(id: EntityId) {\n    return this.remove<T>((item) => item.id === id);\n  },\n};\n\nexport const Items = {\n  push<T>(newItems: T[]) {\n    return (data: T[] | undefined): T[] | undefined => {\n      if (!data) return newItems;\n      return [...data, ...newItems];\n    };\n  },\n  unshift<T>(newItems: T[]) {\n    return (data: T[] | undefined): T[] | undefined => {\n      if (!data) return newItems;\n      return [...newItems, ...data];\n    };\n  },\n  pushAndDedupe<T extends Entity>(newItems: T[]) {\n    return (data: T[] | undefined): T[] | undefined => {\n      if (!data) return newItems;\n      const seen = new Set<EntityId>();\n      const result: T[] = [];\n      for (const item of data) {\n        if (!seen.has(item.id)) {\n          seen.add(item.id);\n          result.push(item);\n        }\n      }\n      for (const item of newItems) {\n        if (!seen.has(item.id)) {\n          seen.add(item.id);\n          result.push(item);\n        }\n      }\n      return result;\n    };\n  },\n  unshiftAndDedupe<T extends Entity>(newItems: T[]) {\n    return (data: T[] | undefined): T[] | undefined => {\n      if (!data) return newItems;\n      const seen = new Set<EntityId>();\n      const result: T[] = [];\n      for (const item of newItems) {\n        if (!seen.has(item.id)) {\n          seen.add(item.id);\n          result.push(item);\n        }\n      }\n      for (const item of data) {\n        if (!seen.has(item.id)) {\n          seen.add(item.id);\n          result.push(item);\n        }\n      }\n      return result;\n    };\n  },\n  update<T>(updater: T, predicate: (item: T) => boolean) {\n    return (data: T[] | undefined): T[] | undefined => {\n      if (!data) return data;\n      return data.map((item) => (predicate(item) ? updater : item));\n    };\n  },\n  updateById<T extends Entity>(updated: T) {\n    return this.update<T>(updated, (item) => item.id === updated.id);\n  },\n  remove<T>(predicate: (item: T) => boolean) {\n    return (data: T[] | undefined): T[] | undefined => {\n      if (!data) return data;\n      return data.filter((item) => !predicate(item));\n    };\n  },\n  removeById<T extends Entity>(id: EntityId) {\n    return this.remove<T>((item) => item.id === id);\n  },\n};\n"],"mappings":"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"}