mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-27 14:11:59 +08:00
feat: implement new pagination types and enhance API documentation
- Introduced `OffsetPaginationParams`, `CursorPaginationParams`, and their corresponding response types to standardize pagination handling across the API. - Updated existing API types and hooks to support both offset and cursor-based pagination, improving data fetching capabilities. - Enhanced documentation with detailed usage examples for pagination, including request parameters and response structures, to aid developers in implementing pagination effectively. - Refactored related components to utilize the new pagination types, ensuring consistency and clarity in data management.
This commit is contained in:
parent
6a6f114946
commit
81bb8e7981
@ -37,7 +37,15 @@ import type {
|
||||
DataRequest,
|
||||
DataResponse,
|
||||
ApiClient,
|
||||
PaginatedResponse
|
||||
// Pagination types
|
||||
OffsetPaginationParams,
|
||||
OffsetPaginationResponse,
|
||||
CursorPaginationParams,
|
||||
CursorPaginationResponse,
|
||||
PaginationResponse,
|
||||
// Query parameter types
|
||||
SortParams,
|
||||
SearchParams
|
||||
} from '@shared/data/api'
|
||||
|
||||
import {
|
||||
@ -45,7 +53,10 @@ import {
|
||||
DataApiError,
|
||||
DataApiErrorFactory,
|
||||
isDataApiError,
|
||||
toDataApiError
|
||||
toDataApiError,
|
||||
// Pagination type guards
|
||||
isOffsetPaginationResponse,
|
||||
isCursorPaginationResponse
|
||||
} from '@shared/data/api'
|
||||
```
|
||||
|
||||
@ -64,12 +75,68 @@ import type { Message, CreateMessageDto } from '@shared/data/api/schemas/message
|
||||
import type { TestItem, CreateTestItemDto } from '@shared/data/api/schemas/test'
|
||||
```
|
||||
|
||||
## Pagination Types
|
||||
|
||||
The API system supports two pagination modes with composable query parameters.
|
||||
|
||||
### Request Parameters
|
||||
|
||||
| Type | Fields | Use Case |
|
||||
|------|--------|----------|
|
||||
| `OffsetPaginationParams` | `page?`, `limit?` | Traditional page-based navigation |
|
||||
| `CursorPaginationParams` | `cursor?`, `limit?` | Infinite scroll, real-time feeds |
|
||||
| `SortParams` | `sortBy?`, `sortOrder?` | Sorting (combine as needed) |
|
||||
| `SearchParams` | `search?` | Text search (combine as needed) |
|
||||
|
||||
### Response Types
|
||||
|
||||
| Type | Fields | Description |
|
||||
|------|--------|-------------|
|
||||
| `OffsetPaginationResponse<T>` | `items`, `total`, `page` | Page-based results |
|
||||
| `CursorPaginationResponse<T>` | `items`, `nextCursor?` | Cursor-based results |
|
||||
| `PaginationResponse<T>` | Union of both | When either mode is acceptable |
|
||||
|
||||
### Usage Examples
|
||||
|
||||
```typescript
|
||||
// Offset pagination with sort and search
|
||||
query?: OffsetPaginationParams & SortParams & SearchParams & {
|
||||
type?: string
|
||||
}
|
||||
response: OffsetPaginationResponse<Item>
|
||||
|
||||
// Cursor pagination for infinite scroll
|
||||
query?: CursorPaginationParams & {
|
||||
userId: string
|
||||
}
|
||||
response: CursorPaginationResponse<Message>
|
||||
```
|
||||
|
||||
### Client-side Calculations
|
||||
|
||||
For `OffsetPaginationResponse`, clients can calculate:
|
||||
```typescript
|
||||
const pageCount = Math.ceil(total / limit)
|
||||
const hasNext = page * limit < total
|
||||
const hasPrev = page > 1
|
||||
```
|
||||
|
||||
For `CursorPaginationResponse`:
|
||||
```typescript
|
||||
const hasNext = nextCursor !== undefined
|
||||
```
|
||||
|
||||
## Adding a New Domain Schema
|
||||
|
||||
1. Create the schema file (e.g., `schemas/topic.ts`):
|
||||
|
||||
```typescript
|
||||
import type { PaginatedResponse } from '../apiTypes'
|
||||
import type {
|
||||
OffsetPaginationParams,
|
||||
OffsetPaginationResponse,
|
||||
SearchParams,
|
||||
SortParams
|
||||
} from '../apiTypes'
|
||||
|
||||
// Domain models
|
||||
export interface Topic {
|
||||
@ -86,7 +153,8 @@ export interface CreateTopicDto {
|
||||
export interface TopicSchemas {
|
||||
'/topics': {
|
||||
GET: {
|
||||
response: PaginatedResponse<Topic> // response is required
|
||||
query?: OffsetPaginationParams & SortParams & SearchParams
|
||||
response: OffsetPaginationResponse<Topic> // response is required
|
||||
}
|
||||
POST: {
|
||||
body: CreateTopicDto
|
||||
@ -152,7 +220,9 @@ const handlers: ApiImplementation = {
|
||||
|
||||
```typescript
|
||||
const topic = await api.get('/topics/123') // Returns Topic
|
||||
const topics = await api.get('/topics', { query: { page: 1 } }) // Returns PaginatedResponse<Topic>
|
||||
const topics = await api.get('/topics', {
|
||||
query: { page: 1, limit: 20, search: 'hello' }
|
||||
}) // Returns OffsetPaginationResponse<Topic>
|
||||
await api.post('/topics', { body: { name: 'New' } }) // Body is typed as CreateTopicDto
|
||||
```
|
||||
|
||||
|
||||
@ -138,79 +138,111 @@ export type { SerializedDataApiError } from './apiErrors'
|
||||
// Pagination Types
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Pagination mode
|
||||
*/
|
||||
export type PaginationMode = 'offset' | 'cursor'
|
||||
// ----- Request Parameters -----
|
||||
|
||||
/**
|
||||
* Pagination parameters for list operations
|
||||
* Offset-based pagination parameters (page + limit)
|
||||
*/
|
||||
export interface PaginationParams {
|
||||
export interface OffsetPaginationParams {
|
||||
/** Page number (1-based) */
|
||||
page?: number
|
||||
/** Items per page */
|
||||
limit?: number
|
||||
/** Page number (offset mode, 1-based) */
|
||||
page?: number
|
||||
/** Cursor (cursor mode) */
|
||||
cursor?: string
|
||||
/** Sort field and direction */
|
||||
sort?: {
|
||||
field: string
|
||||
order: 'asc' | 'desc'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base paginated response (shared fields)
|
||||
* Cursor-based pagination parameters (cursor + limit)
|
||||
*/
|
||||
export interface BasePaginatedResponse<T> {
|
||||
export interface CursorPaginationParams {
|
||||
/** Cursor for next page (undefined for first page) */
|
||||
cursor?: string
|
||||
/** Items per page */
|
||||
limit?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort parameters (independent, combine as needed)
|
||||
*/
|
||||
export interface SortParams {
|
||||
/** Field to sort by */
|
||||
sortBy?: string
|
||||
/** Sort direction */
|
||||
sortOrder?: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
/**
|
||||
* Search parameters (independent, combine as needed)
|
||||
*/
|
||||
export interface SearchParams {
|
||||
/** Search query string */
|
||||
search?: string
|
||||
}
|
||||
|
||||
// ----- Response Types -----
|
||||
|
||||
/**
|
||||
* Offset-based pagination response
|
||||
*/
|
||||
export interface OffsetPaginationResponse<T> {
|
||||
/** Items for current page */
|
||||
items: T[]
|
||||
/** Total number of items */
|
||||
total: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset-based paginated response
|
||||
*/
|
||||
export interface OffsetPaginatedResponse<T> extends BasePaginatedResponse<T> {
|
||||
/** Current page number (1-based) */
|
||||
page: number
|
||||
/** Total number of pages */
|
||||
pageCount: number
|
||||
/** Whether there are more pages */
|
||||
hasNext: boolean
|
||||
/** Whether there are previous pages */
|
||||
hasPrev: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Cursor-based paginated response
|
||||
* Cursor-based pagination response
|
||||
*/
|
||||
export interface CursorPaginatedResponse<T> extends BasePaginatedResponse<T> {
|
||||
export interface CursorPaginationResponse<T> {
|
||||
/** Items for current page */
|
||||
items: T[]
|
||||
/** Next cursor (undefined means no more data) */
|
||||
nextCursor?: string
|
||||
/** Previous cursor */
|
||||
prevCursor?: string
|
||||
}
|
||||
|
||||
// ----- Type Utilities -----
|
||||
|
||||
/**
|
||||
* Unified paginated response (union type)
|
||||
* Infer pagination mode from response type
|
||||
*/
|
||||
export type PaginatedResponse<T> = OffsetPaginatedResponse<T> | CursorPaginatedResponse<T>
|
||||
export type InferPaginationMode<R> = R extends OffsetPaginationResponse<any>
|
||||
? 'offset'
|
||||
: R extends CursorPaginationResponse<any>
|
||||
? 'cursor'
|
||||
: never
|
||||
|
||||
/**
|
||||
* Infer item type from pagination response
|
||||
*/
|
||||
export type InferPaginationItem<R> = R extends OffsetPaginationResponse<infer T>
|
||||
? T
|
||||
: R extends CursorPaginationResponse<infer T>
|
||||
? T
|
||||
: never
|
||||
|
||||
/**
|
||||
* Union type for both pagination responses
|
||||
*/
|
||||
export type PaginationResponse<T> = OffsetPaginationResponse<T> | CursorPaginationResponse<T>
|
||||
|
||||
/**
|
||||
* Type guard: check if response is offset-based
|
||||
*/
|
||||
export function isOffsetPaginatedResponse<T>(response: PaginatedResponse<T>): response is OffsetPaginatedResponse<T> {
|
||||
return 'page' in response && 'pageCount' in response
|
||||
export function isOffsetPaginationResponse<T>(
|
||||
response: PaginationResponse<T>
|
||||
): response is OffsetPaginationResponse<T> {
|
||||
return 'page' in response && 'total' in response
|
||||
}
|
||||
|
||||
/**
|
||||
* Type guard: check if response is cursor-based
|
||||
*/
|
||||
export function isCursorPaginatedResponse<T>(response: PaginatedResponse<T>): response is CursorPaginatedResponse<T> {
|
||||
return 'nextCursor' in response || !('page' in response)
|
||||
export function isCursorPaginationResponse<T>(
|
||||
response: PaginationResponse<T>
|
||||
): response is CursorPaginationResponse<T> {
|
||||
return !('page' in response)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -19,12 +19,18 @@
|
||||
// ============================================================================
|
||||
|
||||
export type {
|
||||
CursorPaginationParams,
|
||||
CursorPaginationResponse,
|
||||
DataRequest,
|
||||
DataResponse,
|
||||
HttpMethod,
|
||||
PaginatedResponse,
|
||||
PaginationParams
|
||||
OffsetPaginationParams,
|
||||
OffsetPaginationResponse,
|
||||
PaginationResponse,
|
||||
SearchParams,
|
||||
SortParams
|
||||
} from './apiTypes'
|
||||
export { isCursorPaginationResponse, isOffsetPaginationResponse } from './apiTypes'
|
||||
|
||||
// ============================================================================
|
||||
// API Schema Type Utilities
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
* These endpoints demonstrate the API patterns and provide testing utilities.
|
||||
*/
|
||||
|
||||
import type { PaginatedResponse, PaginationParams } from '../apiTypes'
|
||||
import type { OffsetPaginationParams, OffsetPaginationResponse, SearchParams, SortParams } from '../apiTypes'
|
||||
|
||||
// ============================================================================
|
||||
// Domain Models & DTOs
|
||||
@ -98,15 +98,15 @@ export interface TestSchemas {
|
||||
'/test/items': {
|
||||
/** List all test items with optional filtering and pagination */
|
||||
GET: {
|
||||
query?: PaginationParams & {
|
||||
/** Search items by title or description */
|
||||
search?: string
|
||||
/** Filter by item type */
|
||||
type?: string
|
||||
/** Filter by status */
|
||||
status?: string
|
||||
}
|
||||
response: PaginatedResponse<TestItem>
|
||||
query?: OffsetPaginationParams &
|
||||
SortParams &
|
||||
SearchParams & {
|
||||
/** Filter by item type */
|
||||
type?: string
|
||||
/** Filter by status */
|
||||
status?: string
|
||||
}
|
||||
response: OffsetPaginationResponse<TestItem>
|
||||
}
|
||||
/** Create a new test item */
|
||||
POST: {
|
||||
@ -147,18 +147,14 @@ export interface TestSchemas {
|
||||
'/test/search': {
|
||||
/** Search test items */
|
||||
GET: {
|
||||
query: {
|
||||
query: OffsetPaginationParams & {
|
||||
/** Search query string */
|
||||
query: string
|
||||
/** Page number for pagination */
|
||||
page?: number
|
||||
/** Number of results per page */
|
||||
limit?: number
|
||||
/** Additional filters */
|
||||
type?: string
|
||||
status?: string
|
||||
}
|
||||
response: PaginatedResponse<TestItem>
|
||||
response: OffsetPaginationResponse<TestItem>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,12 +21,17 @@ export { TestService } from '@data/services/TestService'
|
||||
|
||||
// Re-export types for convenience
|
||||
export type {
|
||||
CursorPaginationParams,
|
||||
CursorPaginationResponse,
|
||||
DataRequest,
|
||||
DataResponse,
|
||||
Middleware,
|
||||
PaginatedResponse,
|
||||
PaginationParams,
|
||||
OffsetPaginationParams,
|
||||
OffsetPaginationResponse,
|
||||
PaginationResponse,
|
||||
RequestContext,
|
||||
ServiceOptions
|
||||
SearchParams,
|
||||
ServiceOptions,
|
||||
SortParams
|
||||
} from '@shared/data/api/apiTypes'
|
||||
export type { CreateTestItemDto, TestItem, UpdateTestItemDto } from '@shared/data/api/schemas/test'
|
||||
|
||||
@ -1,4 +1,9 @@
|
||||
import type { PaginationParams, ServiceOptions } from '@shared/data/api/apiTypes'
|
||||
import type { CursorPaginationParams, OffsetPaginationParams, ServiceOptions } from '@shared/data/api/apiTypes'
|
||||
|
||||
/**
|
||||
* Base pagination params for service layer (supports both modes)
|
||||
*/
|
||||
type BasePaginationParams = (OffsetPaginationParams | CursorPaginationParams) & Record<string, any>
|
||||
|
||||
/**
|
||||
* Standard service interface for data operations
|
||||
@ -14,12 +19,12 @@ export interface IBaseService<T = any, TCreate = any, TUpdate = any> {
|
||||
* Find multiple entities with pagination
|
||||
*/
|
||||
findMany(
|
||||
params: PaginationParams & Record<string, any>,
|
||||
params: BasePaginationParams,
|
||||
options?: ServiceOptions
|
||||
): Promise<{
|
||||
items: T[]
|
||||
total: number
|
||||
hasNext?: boolean
|
||||
total?: number
|
||||
page?: number
|
||||
nextCursor?: string
|
||||
}>
|
||||
|
||||
@ -68,12 +73,12 @@ export interface ISearchableService<T = any, TCreate = any, TUpdate = any> exten
|
||||
*/
|
||||
search(
|
||||
query: string,
|
||||
params?: PaginationParams,
|
||||
params?: BasePaginationParams,
|
||||
options?: ServiceOptions
|
||||
): Promise<{
|
||||
items: T[]
|
||||
total: number
|
||||
hasNext?: boolean
|
||||
total?: number
|
||||
page?: number
|
||||
nextCursor?: string
|
||||
}>
|
||||
}
|
||||
@ -87,12 +92,12 @@ export interface IHierarchicalService<TParent = any, TChild = any, TChildCreate
|
||||
*/
|
||||
getChildren(
|
||||
parentId: string,
|
||||
params?: PaginationParams,
|
||||
params?: BasePaginationParams,
|
||||
options?: ServiceOptions
|
||||
): Promise<{
|
||||
items: TChild[]
|
||||
total: number
|
||||
hasNext?: boolean
|
||||
total?: number
|
||||
page?: number
|
||||
nextCursor?: string
|
||||
}>
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import type { BodyForPath, QueryParamsForPath, ResponseForPath } from '@shared/data/api/apiPaths'
|
||||
import type { ConcreteApiPaths, PaginationMode } from '@shared/data/api/apiTypes'
|
||||
import type { ConcreteApiPaths } from '@shared/data/api/apiTypes'
|
||||
import {
|
||||
isCursorPaginatedResponse,
|
||||
type OffsetPaginatedResponse,
|
||||
type PaginatedResponse
|
||||
isCursorPaginationResponse,
|
||||
type OffsetPaginationResponse,
|
||||
type PaginationResponse
|
||||
} from '@shared/data/api/apiTypes'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import type { KeyedMutator } from 'swr'
|
||||
@ -18,7 +18,7 @@ import { dataApiService } from '../DataApiService'
|
||||
// ============================================================================
|
||||
|
||||
/** Infer item type from paginated response path */
|
||||
type InferPaginatedItem<TPath extends ConcreteApiPaths> = ResponseForPath<TPath, 'GET'> extends PaginatedResponse<
|
||||
type InferPaginatedItem<TPath extends ConcreteApiPaths> = ResponseForPath<TPath, 'GET'> extends PaginationResponse<
|
||||
infer T
|
||||
>
|
||||
? T
|
||||
@ -50,7 +50,7 @@ export interface UseMutationResult<
|
||||
/** useInfiniteQuery result type */
|
||||
export interface UseInfiniteQueryResult<T> {
|
||||
items: T[]
|
||||
pages: PaginatedResponse<T>[]
|
||||
pages: PaginationResponse<T>[]
|
||||
total: number
|
||||
size: number
|
||||
isLoading: boolean
|
||||
@ -61,7 +61,7 @@ export interface UseInfiniteQueryResult<T> {
|
||||
setSize: (size: number | ((size: number) => number)) => void
|
||||
refresh: () => void
|
||||
reset: () => void
|
||||
mutate: KeyedMutator<PaginatedResponse<T>[]>
|
||||
mutate: KeyedMutator<PaginationResponse<T>[]>
|
||||
}
|
||||
|
||||
/** usePaginatedQuery result type */
|
||||
@ -356,7 +356,7 @@ export function useInfiniteQuery<TPath extends ConcreteApiPaths>(
|
||||
/** Items per page (default: 10) */
|
||||
limit?: number
|
||||
/** Pagination mode (default: 'cursor') */
|
||||
mode?: PaginationMode
|
||||
mode?: 'offset' | 'cursor'
|
||||
/** Whether to enable the query (default: true) */
|
||||
enabled?: boolean
|
||||
/** SWR options (including initialSize, revalidateAll, etc.) */
|
||||
@ -368,19 +368,22 @@ export function useInfiniteQuery<TPath extends ConcreteApiPaths>(
|
||||
const enabled = options?.enabled !== false
|
||||
|
||||
const getKey = useCallback(
|
||||
(pageIndex: number, previousPageData: PaginatedResponse<any> | null) => {
|
||||
(pageIndex: number, previousPageData: PaginationResponse<any> | null) => {
|
||||
if (!enabled) return null
|
||||
|
||||
if (previousPageData) {
|
||||
if (mode === 'cursor') {
|
||||
if (!isCursorPaginatedResponse(previousPageData) || !previousPageData.nextCursor) {
|
||||
if (!isCursorPaginationResponse(previousPageData) || !previousPageData.nextCursor) {
|
||||
return null
|
||||
}
|
||||
} else {
|
||||
if (isCursorPaginatedResponse(previousPageData)) {
|
||||
// Offset mode: check if we've reached the end
|
||||
if (isCursorPaginationResponse(previousPageData)) {
|
||||
return null
|
||||
}
|
||||
if (!previousPageData.hasNext) {
|
||||
const offsetData = previousPageData as OffsetPaginationResponse<any>
|
||||
// No more pages if items returned is less than limit or we've fetched all
|
||||
if (offsetData.items.length < limit || pageIndex * limit >= offsetData.total) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
@ -391,7 +394,7 @@ export function useInfiniteQuery<TPath extends ConcreteApiPaths>(
|
||||
limit
|
||||
}
|
||||
|
||||
if (mode === 'cursor' && previousPageData && isCursorPaginatedResponse(previousPageData)) {
|
||||
if (mode === 'cursor' && previousPageData && isCursorPaginationResponse(previousPageData)) {
|
||||
paginationQuery.cursor = previousPageData.nextCursor
|
||||
} else if (mode === 'offset') {
|
||||
paginationQuery.page = pageIndex + 1
|
||||
@ -403,7 +406,7 @@ export function useInfiniteQuery<TPath extends ConcreteApiPaths>(
|
||||
)
|
||||
|
||||
const infiniteFetcher = (key: [ConcreteApiPaths, Record<string, any>?]) => {
|
||||
return getFetcher(key) as Promise<PaginatedResponse<any>>
|
||||
return getFetcher(key) as Promise<PaginationResponse<any>>
|
||||
}
|
||||
|
||||
const swrResult = useSWRInfinite(getKey, infiniteFetcher, {
|
||||
@ -416,7 +419,7 @@ export function useInfiniteQuery<TPath extends ConcreteApiPaths>(
|
||||
})
|
||||
|
||||
const { error, isLoading, isValidating, mutate, size, setSize } = swrResult
|
||||
const data = swrResult.data as PaginatedResponse<any>[] | undefined
|
||||
const data = swrResult.data as PaginationResponse<any>[] | undefined
|
||||
|
||||
const items = useMemo(() => data?.flatMap((p) => p.items) ?? [], [data])
|
||||
|
||||
@ -424,10 +427,13 @@ export function useInfiniteQuery<TPath extends ConcreteApiPaths>(
|
||||
if (!data?.length) return false
|
||||
const last = data[data.length - 1]
|
||||
if (mode === 'cursor') {
|
||||
return isCursorPaginatedResponse(last) && !!last.nextCursor
|
||||
return isCursorPaginationResponse(last) && !!last.nextCursor
|
||||
}
|
||||
return !isCursorPaginatedResponse(last) && (last as OffsetPaginatedResponse<any>).hasNext
|
||||
}, [data, mode])
|
||||
// Offset mode: check if there are more items
|
||||
if (isCursorPaginationResponse(last)) return false
|
||||
const offsetData = last as OffsetPaginationResponse<any>
|
||||
return offsetData.page * limit < offsetData.total
|
||||
}, [data, mode, limit])
|
||||
|
||||
const loadNext = useCallback(() => {
|
||||
if (!hasNext || isValidating) return
|
||||
@ -437,10 +443,18 @@ export function useInfiniteQuery<TPath extends ConcreteApiPaths>(
|
||||
const refresh = useCallback(() => mutate(), [mutate])
|
||||
const reset = useCallback(() => setSize(1), [setSize])
|
||||
|
||||
// Total is only available in offset mode
|
||||
const total = useMemo(() => {
|
||||
if (!data?.length) return 0
|
||||
const first = data[0]
|
||||
if (isCursorPaginationResponse(first)) return 0
|
||||
return (first as OffsetPaginationResponse<any>).total
|
||||
}, [data])
|
||||
|
||||
return {
|
||||
items,
|
||||
pages: data ?? [],
|
||||
total: data?.[0]?.total ?? 0,
|
||||
total,
|
||||
size,
|
||||
isLoading,
|
||||
isRefreshing: isValidating,
|
||||
@ -501,7 +515,8 @@ export function usePaginatedQuery<TPath extends ConcreteApiPaths>(
|
||||
swrOptions: options?.swrOptions
|
||||
})
|
||||
|
||||
const paginatedData = data as PaginatedResponse<any>
|
||||
// usePaginatedQuery is only for offset pagination
|
||||
const paginatedData = data as OffsetPaginationResponse<any> | undefined
|
||||
const items = paginatedData?.items || []
|
||||
const total = paginatedData?.total || 0
|
||||
const totalPages = Math.ceil(total / limit)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { BodyForPath, QueryParamsForPath, ResponseForPath } from '@shared/data/api/apiPaths'
|
||||
import type { ConcreteApiPaths, PaginatedResponse } from '@shared/data/api/apiTypes'
|
||||
import type { ConcreteApiPaths, PaginationResponse } from '@shared/data/api/apiTypes'
|
||||
import type { KeyedMutator } from 'swr'
|
||||
import { vi } from 'vitest'
|
||||
|
||||
@ -146,7 +146,7 @@ export const mockUsePaginatedQuery = vi.fn(
|
||||
limit?: number
|
||||
swrOptions?: any
|
||||
}
|
||||
): ResponseForPath<TPath, 'GET'> extends PaginatedResponse<infer T>
|
||||
): ResponseForPath<TPath, 'GET'> extends PaginationResponse<infer T>
|
||||
? {
|
||||
items: T[]
|
||||
total: number
|
||||
@ -181,7 +181,7 @@ export const mockUsePaginatedQuery = vi.fn(
|
||||
nextPage: vi.fn(),
|
||||
refresh: vi.fn(),
|
||||
reset: vi.fn()
|
||||
} as unknown as ResponseForPath<TPath, 'GET'> extends PaginatedResponse<infer T>
|
||||
} as unknown as ResponseForPath<TPath, 'GET'> extends PaginationResponse<infer T>
|
||||
? {
|
||||
items: T[]
|
||||
total: number
|
||||
|
||||
Loading…
Reference in New Issue
Block a user