@classytic/arc-next 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/query.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { keepPreviousData, useInfiniteQuery, useQuery, useQueryClient } from "@tanstack/react-query";
4
- import { useEffect } from "react";
4
+ import { useEffect, useMemo } from "react";
5
5
 
6
6
  //#region src/query.ts
7
7
  const DEFAULT_QUERY_CONFIG = {
@@ -19,38 +19,68 @@ function getItemId(item) {
19
19
  function normalizePagination(data) {
20
20
  if (!data || typeof data !== "object") return null;
21
21
  const d = data;
22
+ const method = d.method ?? null;
23
+ const isKeyset = method === "keyset" || d.hasMore != null && d.total == null && d.pages == null;
22
24
  const hasTotal = d.total != null || d.totalDocs != null;
23
25
  const hasPages = d.pages != null || d.totalPages != null;
24
- if (!hasTotal && !hasPages) return null;
26
+ if (!hasTotal && !hasPages && !isKeyset) return null;
25
27
  return {
28
+ method,
26
29
  total: Number(d.total ?? d.totalDocs ?? 0),
27
- pages: Number(d.pages ?? d.totalPages ?? 1),
28
- page: Number(d.page ?? d.currentPage ?? 1),
30
+ pages: Number(d.pages ?? d.totalPages ?? (isKeyset ? 0 : 1)),
31
+ page: Number(d.page ?? d.currentPage ?? (isKeyset ? 0 : 1)),
29
32
  limit: Number(d.limit ?? 10),
30
33
  hasNext: Boolean(d.hasNext ?? d.hasNextPage ?? d.hasMore ?? false),
31
- hasPrev: Boolean(d.hasPrev ?? d.hasPrevPage ?? false)
34
+ hasPrev: Boolean(d.hasPrev ?? d.hasPrevPage ?? false),
35
+ ...isKeyset ? { next: d.next ?? null } : {}
32
36
  };
33
37
  }
38
+ /** Well-known keys checked in order for list responses. */
39
+ const LIST_KEYS = [
40
+ "docs",
41
+ "data",
42
+ "items",
43
+ "results"
44
+ ];
45
+ /** Well-known keys checked in order for detail responses. */
46
+ const DETAIL_KEYS = [
47
+ "data",
48
+ "doc",
49
+ "item",
50
+ "result"
51
+ ];
34
52
  function extractItems(data) {
35
53
  if (!data) return [];
36
54
  if (Array.isArray(data)) return data;
37
55
  if (typeof data !== "object") return [];
38
56
  const d = data;
39
- const items = d.docs ?? d.data ?? d.items ?? d.results;
40
- return Array.isArray(items) ? items : [];
57
+ for (const key of LIST_KEYS) if (Array.isArray(d[key])) return d[key];
58
+ for (const value of Object.values(d)) if (Array.isArray(value)) return value;
59
+ return [];
41
60
  }
42
61
  function extractItem(data) {
43
- if (!data) return null;
44
- if (typeof data !== "object") return null;
62
+ if (data == null) return null;
63
+ if (typeof data !== "object") return data;
45
64
  const d = data;
46
- return d.data ?? d;
65
+ for (const key of DETAIL_KEYS) if (d[key] != null) return d[key];
66
+ return d;
47
67
  }
48
68
  function updateListCache(listData, updater) {
49
69
  if (!listData) return listData;
50
70
  if (Array.isArray(listData)) return updater(listData);
51
71
  if (typeof listData !== "object") return listData;
52
72
  const d = listData;
53
- const arrayField = "docs" in d ? "docs" : Array.isArray(d.data) ? "data" : "items" in d && Array.isArray(d.items) ? "items" : "results" in d && Array.isArray(d.results) ? "results" : null;
73
+ let arrayField = null;
74
+ for (const key of LIST_KEYS) if (Array.isArray(d[key])) {
75
+ arrayField = key;
76
+ break;
77
+ }
78
+ if (!arrayField) {
79
+ for (const [key, value] of Object.entries(d)) if (Array.isArray(value)) {
80
+ arrayField = key;
81
+ break;
82
+ }
83
+ }
54
84
  if (!arrayField) return listData;
55
85
  const updated = updater(d[arrayField]);
56
86
  const original = d[arrayField];
@@ -107,7 +137,7 @@ function createCacheUtils(KEYS) {
107
137
  removeDetail: (client, id) => client.removeQueries({ queryKey: KEYS.detail(id) })
108
138
  };
109
139
  }
110
- function createListQuery({ queryKey, queryFn, enabled = true, options = {}, prefillDetailCache = true, detailKeyBuilder, select }) {
140
+ function useListQuery({ queryKey, queryFn, enabled = true, options = {}, prefillDetailCache = true, detailKeyBuilder, select }) {
111
141
  const queryClient = useQueryClient();
112
142
  const query = useQuery({
113
143
  queryKey,
@@ -118,8 +148,8 @@ function createListQuery({ queryKey, queryFn, enabled = true, options = {}, pref
118
148
  ...select ? { select } : {},
119
149
  placeholderData: keepPreviousData
120
150
  });
121
- const items = extractItems(query.data);
122
- const pagination = normalizePagination(query.data);
151
+ const items = useMemo(() => extractItems(query.data), [query.data]);
152
+ const pagination = useMemo(() => normalizePagination(query.data), [query.data]);
123
153
  useEffect(() => {
124
154
  if (!prefillDetailCache || !detailKeyBuilder || items.length === 0) return;
125
155
  items.forEach((item) => {
@@ -145,7 +175,7 @@ function createListQuery({ queryKey, queryFn, enabled = true, options = {}, pref
145
175
  data: query.data
146
176
  };
147
177
  }
148
- function createDetailQuery({ queryKey, queryFn, enabled = true, options = {}, select }) {
178
+ function useDetailQuery({ queryKey, queryFn, enabled = true, options = {}, select }) {
149
179
  const query = useQuery({
150
180
  queryKey,
151
181
  queryFn: ({ signal }) => queryFn({ signal }),
@@ -166,7 +196,7 @@ function createDetailQuery({ queryKey, queryFn, enabled = true, options = {}, se
166
196
  data: query.data
167
197
  };
168
198
  }
169
- function createInfiniteListQuery({ queryKey, queryFn, enabled = true, options = {}, initialPageParam = 1, getNextPageParam, getPreviousPageParam }) {
199
+ function useInfiniteListQuery({ queryKey, queryFn, enabled = true, options = {}, initialPageParam = 1, getNextPageParam, getPreviousPageParam }) {
170
200
  const query = useInfiniteQuery({
171
201
  queryKey,
172
202
  queryFn: ({ pageParam, signal }) => queryFn({
@@ -181,7 +211,7 @@ function createInfiniteListQuery({ queryKey, queryFn, enabled = true, options =
181
211
  ...options
182
212
  });
183
213
  return {
184
- items: query.data?.pages.flatMap((page) => extractItems(page)) ?? [],
214
+ items: useMemo(() => query.data?.pages.flatMap((page) => extractItems(page)) ?? [], [query.data]),
185
215
  hasNextPage: query.hasNextPage,
186
216
  hasPreviousPage: query.hasPreviousPage,
187
217
  isFetchingNextPage: query.isFetchingNextPage,
@@ -197,7 +227,12 @@ function createInfiniteListQuery({ queryKey, queryFn, enabled = true, options =
197
227
  data: query.data
198
228
  };
199
229
  }
230
+ /** @deprecated Use `useListQuery` */
231
+ const createListQuery = useListQuery;
232
+ /** @deprecated Use `useDetailQuery` */
233
+ const createDetailQuery = useDetailQuery;
234
+ /** @deprecated Use `useInfiniteListQuery` */
235
+ const createInfiniteListQuery = useInfiniteListQuery;
200
236
 
201
237
  //#endregion
202
- export { DEFAULT_QUERY_CONFIG, createCacheUtils, createDetailQuery, createInfiniteListQuery, createListQuery, createQueryKeys, getItemId, updateListCache };
203
- //# sourceMappingURL=query.js.map
238
+ export { DEFAULT_QUERY_CONFIG, createCacheUtils, createDetailQuery, createInfiniteListQuery, createListQuery, createQueryKeys, extractItem, getItemId, updateListCache, useDetailQuery, useInfiniteListQuery, useListQuery };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/arc-next",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "React + TanStack Query SDK for Arc resources",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -23,7 +23,13 @@
23
23
  "arc",
24
24
  "mongokit"
25
25
  ],
26
+ "main": "./dist/hooks.js",
27
+ "types": "./dist/hooks.d.ts",
26
28
  "exports": {
29
+ ".": {
30
+ "types": "./dist/hooks.d.ts",
31
+ "default": "./dist/hooks.js"
32
+ },
27
33
  "./client": {
28
34
  "types": "./dist/client.d.ts",
29
35
  "default": "./dist/client.js"
@@ -76,7 +82,7 @@
76
82
  "react": "^19.0.0"
77
83
  },
78
84
  "devDependencies": {
79
- "@tanstack/react-query": "^5.0.0",
85
+ "@tanstack/react-query": "^5.95.2",
80
86
  "@testing-library/jest-dom": "^6.9.1",
81
87
  "@testing-library/react": "^16.3.2",
82
88
  "@types/react": "^19.0.0",
@@ -84,7 +90,7 @@
84
90
  "jsdom": "^28.1.0",
85
91
  "react": "^19.0.0",
86
92
  "react-dom": "^19.2.4",
87
- "tsdown": "^0.20.3",
93
+ "tsdown": "^0.21.4",
88
94
  "typescript": "^5.7.2",
89
95
  "vitest": "^4.0.18"
90
96
  }
package/dist/api.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"api.d.ts","names":[],"sources":["../src/api.ts"],"mappings":"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"}
package/dist/api.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"api.js","names":[],"sources":["../src/api.ts"],"sourcesContent":["import { handleApiRequest, createQueryString } from './client.js';\nimport type { ApiRequestOptions, ArcClient } from './client.js';\n\n// ============================================================================\n// Populate Types\n// ============================================================================\n\nexport interface PopulateOption {\n path: string;\n select?: string;\n match?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Response Types\n// ============================================================================\n\nexport interface ApiResponse<T = unknown> {\n success: boolean;\n data?: T;\n message?: string;\n}\n\nexport interface OffsetPaginationResponse<T = unknown> {\n success: boolean;\n method: 'offset';\n docs: T[];\n page: number;\n limit: number;\n total: number;\n pages: number;\n hasNext: boolean;\n hasPrev: boolean;\n warning?: string;\n}\n\nexport interface KeysetPaginationResponse<T = unknown> {\n success: boolean;\n method: 'keyset';\n docs: T[];\n limit: number;\n hasMore: boolean;\n next: string | null;\n}\n\nexport interface AggregatePaginationResponse<T = unknown> {\n success: boolean;\n method: 'aggregate';\n docs: T[];\n page: number;\n limit: number;\n total: number;\n pages: number;\n hasNext: boolean;\n hasPrev: boolean;\n warning?: string;\n}\n\nexport type PaginatedResponse<T = unknown> =\n | OffsetPaginationResponse<T>\n | KeysetPaginationResponse<T>\n | AggregatePaginationResponse<T>;\n\nexport interface DeleteResponse {\n success: boolean;\n data?: {\n message?: string;\n id?: string;\n soft?: boolean;\n };\n}\n\n// ============================================================================\n// Request Types\n// ============================================================================\n\nexport type SortDirection = 1 | -1 | 'asc' | 'desc';\nexport type SortSpec = Record<string, SortDirection> | string;\n\nexport type FilterOperator =\n | 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte'\n | 'in' | 'nin'\n | 'contains' | 'startsWith' | 'endsWith' | 'regex';\n\nexport interface QueryParams {\n page?: number;\n limit?: number;\n after?: string;\n cursor?: string;\n sort?: string;\n select?: string;\n populate?: string | string[];\n populateOptions?: PopulateOption[];\n lean?: boolean | 'true' | 'false';\n [key: string]: unknown;\n}\n\nexport interface RequestOptions {\n token?: string | null;\n organizationId?: string | null;\n cache?: RequestCache;\n revalidate?: number;\n tags?: string[];\n headerOptions?: Record<string, string>;\n responseType?: 'json' | 'blob' | 'text';\n signal?: AbortSignal;\n}\n\nexport interface BaseApiConfig {\n basePath?: string;\n defaultParams?: {\n limit?: number;\n page?: number;\n [key: string]: unknown;\n };\n cache?: RequestCache;\n headers?: Record<string, string>;\n client?: ArcClient;\n}\n\n// ============================================================================\n// Request Function Type\n// ============================================================================\n\ntype RequestFn = <T = unknown>(\n method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE',\n endpoint: string,\n options?: ApiRequestOptions,\n) => Promise<T>;\n\n// ============================================================================\n// Base API Class\n// ============================================================================\n\nexport class BaseApi<\n TDoc = Record<string, unknown>,\n TCreate = Partial<TDoc>,\n TUpdate = Partial<TDoc>\n> {\n readonly entity: string;\n readonly config: Required<Omit<BaseApiConfig, 'client'>>;\n readonly baseUrl: string;\n private readonly requestFn: RequestFn;\n\n constructor(entity: string, config: BaseApiConfig = {}) {\n this.entity = entity;\n this.requestFn = config.client?.request ?? handleApiRequest;\n this.config = {\n basePath: config.basePath ?? '/api/v1',\n defaultParams: {\n limit: 10,\n page: 1,\n ...(config.defaultParams || {}),\n },\n cache: config.cache ?? 'no-store',\n headers: {\n ...(config.headers || {}),\n },\n };\n\n this.baseUrl = `${this.config.basePath}/${this.entity}`;\n }\n\n /** Merge per-instance headers into request options */\n private withHeaders(options: ApiRequestOptions): ApiRequestOptions {\n const instanceHeaders = this.config.headers;\n if (!instanceHeaders || Object.keys(instanceHeaders).length === 0) return options;\n return {\n ...options,\n headerOptions: { ...instanceHeaders, ...(options.headerOptions ?? {}) },\n };\n }\n\n createQueryString(params: Record<string, unknown> = {}): string {\n return createQueryString(params);\n }\n\n prepareParams(params: QueryParams = {}): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const CRITICAL_FILTERS = ['organizationId', 'ownerId'];\n\n Object.entries(params).forEach(([key, value]) => {\n if (CRITICAL_FILTERS.includes(key)) {\n result[key] = value || null;\n return;\n }\n\n if (key === 'populateOptions') {\n if (Array.isArray(value) && value.length > 0) {\n result[key] = value;\n }\n return;\n }\n\n if (value !== undefined && value !== '') {\n if (['page', 'limit'].includes(key)) {\n result[key] = parseInt(String(value)) || (key === 'page' ? 1 : 10);\n } else if (Array.isArray(value)) {\n if (value.length > 1) {\n result[`${key}[in]`] = value.join(',');\n } else if (value.length === 1) {\n result[key] = value[0];\n }\n } else {\n result[key] = value;\n }\n }\n });\n\n return result;\n }\n\n async getAll({\n token = null,\n organizationId = null,\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n } = {}): Promise<PaginatedResponse<TDoc>> {\n const processedParams = this.prepareParams(params);\n const queryString = this.createQueryString(processedParams);\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', `${this.baseUrl}?${queryString}`, this.withHeaders(requestOptions));\n }\n\n async getById({\n token = null,\n organizationId = null,\n id,\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n params?: { select?: string; populate?: string | string[] };\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n if (!id) throw new Error('ID is required');\n\n const queryString = this.createQueryString(params);\n const url = queryString ? `${this.baseUrl}/${id}?${queryString}` : `${this.baseUrl}/${id}`;\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', url, this.withHeaders(requestOptions));\n }\n\n async create({\n token,\n organizationId = null,\n data,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n data: TCreate;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n const requestOptions: ApiRequestOptions = {\n body: data,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('POST', this.baseUrl, this.withHeaders(requestOptions));\n }\n\n async update({\n token,\n organizationId = null,\n id,\n data,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n data: TUpdate;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n if (!id) throw new Error('ID is required');\n\n const requestOptions: ApiRequestOptions = {\n body: data,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('PATCH', `${this.baseUrl}/${id}`, this.withHeaders(requestOptions));\n }\n\n async delete({\n token,\n organizationId = null,\n id,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<DeleteResponse> {\n if (!id) throw new Error('ID is required');\n\n const requestOptions: ApiRequestOptions = { ...options };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('DELETE', `${this.baseUrl}/${id}`, this.withHeaders(requestOptions));\n }\n\n async upload({\n token,\n organizationId = null,\n data,\n id,\n path,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n data: FormData;\n /** Resource ID — shorthand for path, appended as `baseUrl/{id}/upload` */\n id?: string;\n /** Custom sub-path appended as `baseUrl/{path}`. Takes precedence over `id`. */\n path?: string;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n const suffix = path ?? (id ? `${id}/upload` : undefined);\n const url = suffix ? `${this.baseUrl}/${suffix}` : this.baseUrl;\n\n const requestOptions: ApiRequestOptions = {\n body: data,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('POST', url, this.withHeaders(requestOptions));\n }\n\n async search({\n token = null,\n organizationId = null,\n searchParams = {},\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n searchParams?: Record<string, unknown>;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n } = {}): Promise<PaginatedResponse<TDoc>> {\n const queryParams = { ...params, ...searchParams };\n const processedParams = this.prepareParams(queryParams);\n const queryString = this.createQueryString(processedParams);\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', `${this.baseUrl}?${queryString}`, this.withHeaders(requestOptions));\n }\n\n async findBy({\n token = null,\n organizationId = null,\n field,\n value,\n operator,\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n field: string;\n value: unknown;\n operator?: FilterOperator;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<PaginatedResponse<TDoc>> {\n if (!field || value === undefined) {\n throw new Error('Field and value are required');\n }\n\n const queryParams: QueryParams = { ...params };\n\n if (operator) {\n queryParams[`${field}[${operator}]`] = Array.isArray(value) ? value.join(',') : value;\n } else {\n queryParams[field] = value;\n }\n\n const processedParams = this.prepareParams(queryParams);\n const queryString = this.createQueryString(processedParams);\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', `${this.baseUrl}?${queryString}`, this.withHeaders(requestOptions));\n }\n\n async request<TResponse = unknown>(\n method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE',\n endpoint: string,\n {\n token,\n organizationId = null,\n data,\n params,\n options = {},\n }: {\n token?: string;\n organizationId?: string | null;\n data?: unknown;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n } = {}\n ): Promise<TResponse> {\n let url = endpoint;\n\n if (params) {\n const processedParams = this.prepareParams(params);\n const queryString = this.createQueryString(processedParams);\n url = `${endpoint}?${queryString}`;\n }\n\n const requestOptions: ApiRequestOptions = {\n body: data,\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn(method, url, this.withHeaders(requestOptions));\n }\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport function createCrudApi<\n TDoc = Record<string, unknown>,\n TCreate = Partial<TDoc>,\n TUpdate = Partial<TDoc>\n>(entity: string, config: BaseApiConfig = {}): BaseApi<TDoc, TCreate, TUpdate> {\n return new BaseApi<TDoc, TCreate, TUpdate>(entity, config);\n}\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\nexport type ExtractDoc<T> = T extends PaginatedResponse<infer D> ? D : never;\n\nexport function isOffsetPagination<T>(\n response: PaginatedResponse<T>\n): response is OffsetPaginationResponse<T> {\n return response.method === 'offset';\n}\n\nexport function isKeysetPagination<T>(\n response: PaginatedResponse<T>\n): response is KeysetPaginationResponse<T> {\n return response.method === 'keyset';\n}\n\nexport function isAggregatePagination<T>(\n response: PaginatedResponse<T>\n): response is AggregatePaginationResponse<T> {\n return response.method === 'aggregate';\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"mappings":";UAIiB,YAAA;EACf,OAAA,GAAU,OAAA;EACV,KAAA,GAAQ,OAAA;AAAA;AAAA,KAGE,aAAA;EACV,IAAA,GAAO,IAAA,UAAc,OAAA;IAAY,MAAA;EAAA;EACjC,OAAA,GAAU,IAAA,UAAc,OAAA;IAAY,MAAA;EAAA;AAAA;AAAA,UAOrB,kBAAA;EACf,MAAA;EACA,UAAA;EACA,IAAA;EACA,QAAA;EACA,MAAA,EAAQ,UAAA;AAAA;;;;;;;AALV;;;;;;;;cAsBa,WAAA,SAAoB,KAAA;EAAA,SACtB,MAAA;EAAA,SACA,UAAA;EAAA,SACA,IAAA;EAAA,SACA,QAAA;EAAA,SACA,MAAA,EAAQ,UAAA;cAEL,OAAA,UAAiB,OAAA,EAAS,kBAAA;EAFrB;EAAA,IAab,WAAA,CAAA,GAAe,MAAA;AAAA;;;;iBASL,aAAA,CAAc,KAAA,YAAiB,KAAA,IAAS,WAAA;AAAA,UAQvC,YAAA;EACf,OAAA;EACA,cAAA;EACA,cAAA,GAAiB,MAAA;EAjCR;;;;;EAuCT,QAAA;AAAA;;;;AAjBF;;;;;;;iBAgCgB,eAAA,CAAgB,MAAA,EAAQ,YAAA;;AAxBxC;;iBA+BgB,WAAA,CAAA;AAAA,UAQC,UAAA;EACf,QAAA;EACA,QAAA;AAAA;;;;;AAjBF;;;;;AAOA;;;;;iBA6BgB,aAAA,CAAc,MAAA,EAAQ,UAAA;;;;iBAOtB,cAAA,CAAA;EAAoB,KAAA;EAAsB,cAAA;AAAA;AAAA,KAW9C,UAAA;AAAA,UAEK,iBAAA;EACf,IAAA;EACA,KAAA;EACA,cAAA;EACA,UAAA;EACA,aAAA,GAAgB,MAAA;EAChB,IAAA;EACA,KAAA,GAAQ,YAAA;EACR,MAAA,GAAS,WAAA;AAAA;AAAA,UAGM,YAAA;EACf,IAAA,EAAM,IAAA;EACN,QAAA,EAAU,QAAA;AAAA;AAAA,UAGK,YAAA;EACf,IAAA;EACA,QAAA,EAAU,QAAA;AAAA;AAAA,UAOK,eAAA,SAAwB,YAAA;EACvC,KAAA,GAAQ,YAAA;EACR,UAAA,GAAa,aAAA;AAAA;AAAA,UAGE,SAAA;EACf,OAAA,gBAAuB,MAAA,EAAQ,UAAA,EAAY,QAAA,UAAkB,OAAA,GAAU,iBAAA,KAAsB,OAAA,CAAQ,CAAA;EACrG,MAAA,EAAQ,YAAA;EACR,KAAA,GAAQ,YAAA;EACR,UAAA,GAAa,aAAA;AAAA;;;;;AAvBf;;;;;;;;;iBAuCgB,YAAA,CAAa,MAAA,EAAQ,eAAA,GAAkB,SAAA;AAlCvD;;;;;;;;AAAA,iBA2KsB,gBAAA,aAAA,CACpB,MAAA,EAAQ,UAAA,EACR,QAAA,UACA,OAAA,GAAS,iBAAA,GACR,OAAA,CAAQ,CAAA;AAtKX;;;;;;;;;;;;;;;AAKA;AALA,iBAmMgB,iBAAA,WAA4B,MAAA,kBAAA,CAAyB,MAAA,GAAQ,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["// ============================================================================\n// Shared Types (used by client, mutation, and hooks)\n// ============================================================================\n\nexport interface ToastHandler {\n success: (message: string) => void;\n error: (message: string) => void;\n}\n\nexport type UseRouterHook = () => {\n push: (href: string, options?: { scroll?: boolean }) => void;\n replace: (href: string, options?: { scroll?: boolean }) => void;\n};\n\n// ============================================================================\n// ArcApiError\n// ============================================================================\n\nexport interface ArcApiErrorOptions {\n status: number;\n statusText: string;\n json: unknown;\n endpoint: string;\n method: HttpMethod;\n}\n\n/**\n * Rich API error with status code, response payload, and request metadata.\n * Extends Error so existing `catch (e) { if (e instanceof Error) }` still works.\n *\n * @example\n * try {\n * await handleApiRequest('POST', '/users', { body: data });\n * } catch (error) {\n * if (isArcApiError(error)) {\n * console.log(error.status); // 422\n * console.log(error.fieldErrors); // { email: 'already taken' }\n * }\n * }\n */\nexport class ArcApiError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly json: unknown;\n readonly endpoint: string;\n readonly method: HttpMethod;\n\n constructor(message: string, options: ArcApiErrorOptions) {\n super(message);\n this.name = 'ArcApiError';\n this.status = options.status;\n this.statusText = options.statusText;\n this.json = options.json;\n this.endpoint = options.endpoint;\n this.method = options.method;\n }\n\n /** Extract field-level validation errors if present (e.g. `{ field: \"message\" }`) */\n get fieldErrors(): Record<string, string> | null {\n const j = this.json as { errors?: Record<string, string> } | null;\n return j?.errors ?? null;\n }\n}\n\n/**\n * Type guard for ArcApiError.\n */\nexport function isArcApiError(error: unknown): error is ArcApiError {\n return error instanceof ArcApiError;\n}\n\n// ============================================================================\n// Client Configuration\n// ============================================================================\n\nexport interface ClientConfig {\n baseUrl: string;\n internalApiKey?: string;\n defaultHeaders?: Record<string, string>;\n /**\n * Auth mode for the API client.\n * - 'bearer' (default): Requires a token for authenticated requests. Queries are disabled until a token is provided.\n * - 'cookie': Auth is handled via HTTP-only cookies (e.g. Better Auth). Queries are always enabled — no token needed.\n */\n authMode?: 'bearer' | 'cookie';\n}\n\nlet clientConfig: ClientConfig | null = null;\n\n/**\n * Configure the API client. Call once at app init before any API requests.\n *\n * @example\n * // Bearer token auth (default)\n * configureClient({ baseUrl: process.env.NEXT_PUBLIC_API_URL! });\n *\n * // Cookie-based auth (e.g. Better Auth)\n * configureClient({ baseUrl: process.env.NEXT_PUBLIC_API_URL!, authMode: 'cookie' });\n */\nexport function configureClient(config: ClientConfig): void {\n clientConfig = config;\n}\n\n/**\n * Get the configured auth mode. Returns 'bearer' if not configured.\n */\nexport function getAuthMode(): 'bearer' | 'cookie' {\n return clientConfig?.authMode ?? 'bearer';\n}\n\n// ============================================================================\n// Auth Configuration\n// ============================================================================\n\nexport interface AuthConfig {\n getToken?: () => string | null;\n getOrgId?: () => string | null;\n}\n\nlet authConfig: AuthConfig | null = null;\n\n/**\n * Configure auth context for automatic token/orgId injection.\n * When configured, hooks auto-inject these values so you don't need to pass them manually.\n *\n * @example\n * // Cookie auth (no token needed)\n * configureAuth({ getOrgId: () => currentOrg.id });\n *\n * // Bearer auth\n * configureAuth({\n * getToken: () => session?.accessToken ?? null,\n * getOrgId: () => currentOrg?.id ?? null,\n * });\n */\nexport function configureAuth(config: AuthConfig): void {\n authConfig = config;\n}\n\n/**\n * Get the current auth context. Returns nulls when not configured.\n */\nexport function getAuthContext(): { token: string | null; organizationId: string | null } {\n return {\n token: authConfig?.getToken?.() ?? null,\n organizationId: authConfig?.getOrgId?.() ?? null,\n };\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';\n\nexport interface ApiRequestOptions {\n body?: unknown;\n token?: string | null;\n organizationId?: string | null;\n revalidate?: number;\n headerOptions?: Record<string, string>;\n tags?: string[];\n cache?: RequestCache;\n signal?: AbortSignal;\n}\n\nexport interface BlobResponse {\n data: Blob;\n response: Response;\n}\n\nexport interface TextResponse {\n data: string;\n response: Response;\n}\n\n// ============================================================================\n// Multi-Client Support\n// ============================================================================\n\nexport interface ArcClientConfig extends ClientConfig {\n toast?: ToastHandler;\n navigation?: UseRouterHook;\n}\n\nexport interface ArcClient {\n request: <T = unknown>(method: HttpMethod, endpoint: string, options?: ApiRequestOptions) => Promise<T>;\n config: ClientConfig;\n toast?: ToastHandler;\n navigation?: UseRouterHook;\n}\n\n/**\n * Create an isolated API client for a specific backend.\n * Use this when your app needs to talk to multiple APIs.\n *\n * @example\n * const analyticsClient = createClient({\n * baseUrl: 'https://analytics.example.com',\n * toast: { success: toast.success, error: toast.error },\n * navigation: useRouter,\n * });\n *\n * const eventsApi = createCrudApi('events', { client: analyticsClient });\n */\nexport function createClient(config: ArcClientConfig): ArcClient {\n const { toast, navigation, ...clientCfg } = config;\n return {\n request: <T = unknown>(method: HttpMethod, endpoint: string, options?: ApiRequestOptions) =>\n executeRequest<T>(clientCfg, method, endpoint, options),\n config: clientCfg,\n toast,\n navigation,\n };\n}\n\n// ============================================================================\n// Core Request Logic\n// ============================================================================\n\nasync function executeRequest<T = unknown>(\n config: ClientConfig,\n method: HttpMethod,\n endpoint: string,\n options: ApiRequestOptions = {},\n): Promise<T> {\n const {\n body,\n token,\n organizationId,\n revalidate,\n headerOptions,\n tags,\n cache,\n signal,\n } = options;\n\n try {\n let headers: Record<string, string> = {\n ...(organizationId ? { 'x-organization-id': organizationId } : {}),\n ...(config.defaultHeaders ?? {}),\n };\n\n if (config.internalApiKey) {\n headers['x-internal-api-key'] = config.internalApiKey;\n }\n\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n if (body !== undefined && body !== null && !(body instanceof FormData)) {\n headers['Content-Type'] = 'application/json';\n }\n\n if (headerOptions) {\n headers = { ...headers, ...headerOptions };\n }\n\n const fetchOptions: RequestInit & { next?: { revalidate?: number; tags?: string[] } } = {\n method,\n headers,\n credentials: 'include',\n ...(signal ? { signal } : {}),\n };\n\n if (body !== undefined && body !== null) {\n fetchOptions.body = body instanceof FormData ? body : JSON.stringify(body);\n }\n\n if (cache) {\n fetchOptions.cache = cache;\n }\n if (revalidate !== undefined) {\n fetchOptions.next = { ...fetchOptions.next, revalidate };\n }\n if (tags) {\n fetchOptions.next = { ...fetchOptions.next, tags };\n }\n\n const response = await fetch(`${config.baseUrl}${endpoint}`, fetchOptions);\n\n if (!response.ok) {\n const json = await response.json().catch(() => null);\n throw new ArcApiError(\n (json as { message?: string } | null)?.message || response.statusText,\n {\n status: response.status,\n statusText: response.statusText,\n json,\n endpoint,\n method,\n }\n );\n }\n\n const contentType = response.headers.get('Content-Type');\n\n let data: unknown;\n\n if (contentType?.includes('application/json')) {\n data = await response.json();\n } else if (contentType?.includes('application/pdf') || contentType?.includes('image/')) {\n const blobData = await response.blob();\n data = { data: blobData, response };\n } else if (contentType?.includes('text/csv')) {\n const csvData = await response.blob();\n data = { data: csvData, response };\n } else if (contentType?.includes('text/')) {\n const text = await response.text();\n data = { data: text, response };\n } else {\n try {\n const blob = await response.clone().blob();\n data = { data: blob, response };\n } catch {\n const text = await response.text();\n data = { data: text, response };\n }\n }\n\n return data as T;\n } catch (error) {\n if (error instanceof ArcApiError) throw error;\n throw new Error(\n error instanceof Error ? error.message : 'An error occurred while fetching data.'\n );\n }\n}\n\n// ============================================================================\n// API Request Handler (Global — uses configureClient singleton)\n// ============================================================================\n\n/**\n * Universal API request handler.\n * Handles JSON, binary (PDF, images), CSV, and text responses.\n *\n * @example\n * const { success, data } = await handleApiRequest<ApiResponse<User>>('GET', '/users/me');\n * const response = await handleApiRequest<PaginatedResponse<Product>>('GET', '/products?page=1');\n */\nexport async function handleApiRequest<T = unknown>(\n method: HttpMethod,\n endpoint: string,\n options: ApiRequestOptions = {},\n): Promise<T> {\n if (!clientConfig) {\n throw new Error(\n 'arc-next: Client not configured. Call configureClient({ baseUrl }) before making API requests.'\n );\n }\n return executeRequest<T>(clientConfig, method, endpoint, options);\n}\n\n// ============================================================================\n// Query String Utilities\n// ============================================================================\n\n/**\n * Creates query string from parameters.\n * Supports: arrays as field[in]=value1,value2, populateOptions with field selection.\n *\n * @example\n * createQueryString({ page: 1, limit: 10, status: 'active' })\n * // => 'page=1&limit=10&status=active'\n *\n * createQueryString({ roles: ['admin', 'user'] })\n * // => 'roles[in]=admin,user'\n *\n * createQueryString({\n * populateOptions: [{ path: 'employeeId', select: 'name email' }]\n * })\n * // => 'populate[employeeId][select]=name,email'\n */\nexport function createQueryString<T extends Record<string, unknown>>(params: T = {} as T): string {\n const searchParams = new URLSearchParams();\n\n Object.entries(params).forEach(([key, value]) => {\n if (value === undefined || value === '') return;\n\n if (key === 'populateOptions' && Array.isArray(value)) {\n (value as Array<{ path: string; select?: string; match?: Record<string, unknown> }>).forEach(\n (opt) => {\n if (opt.select) {\n const selectFields = opt.select.replace(/\\s+/g, ',');\n searchParams.append(`populate[${opt.path}][select]`, selectFields);\n }\n if (opt.match) {\n searchParams.append(`populate[${opt.path}][match]`, JSON.stringify(opt.match));\n }\n if (!opt.select && !opt.match) {\n const existing = searchParams.get('populate');\n if (existing) {\n searchParams.set('populate', `${existing},${opt.path}`);\n } else {\n searchParams.append('populate', opt.path);\n }\n }\n }\n );\n return;\n }\n\n if (Array.isArray(value)) {\n if (value.length > 1) {\n searchParams.append(`${key}[in]`, value.join(','));\n } else if (value.length === 1) {\n searchParams.append(key, String(value[0]));\n }\n } else if (value === null) {\n searchParams.append(key, 'null');\n } else {\n searchParams.append(key, String(value));\n }\n });\n\n return searchParams.toString();\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;;;;UA0CiB,OAAA,cAAqB,OAAA,CAAQ,CAAA,aAAc,OAAA,CAAQ,CAAA;EAClE,MAAA,GAAS,OAAA;IACP,KAAA;IACA,cAAA;IACA,MAAA,GAAS,MAAA;IACT,OAAA;MAAY,MAAA,GAAS,WAAA;MAAA,CAAc,GAAA;IAAA;EAAA,MAC/B,OAAA;EAEN,OAAA,GAAU,OAAA;IACR,EAAA;IACA,KAAA;IACA,cAAA;IACA,MAAA;MAAW,MAAA;MAAiB,QAAA;IAAA;IAC5B,OAAA;MAAY,MAAA,GAAS,WAAA;MAAA,CAAc,GAAA;IAAA;EAAA,MAC/B,OAAA;EAEN,MAAA,GAAS,OAAA;IACP,KAAA;IACA,cAAA;IACA,IAAA,EAAM,OAAA;EAAA,MACF,OAAA;EAEN,MAAA,GAAS,OAAA;IACP,KAAA;IACA,cAAA;IACA,EAAA;IACA,IAAA,EAAM,OAAA;EAAA,MACF,OAAA;EAEN,MAAA,GAAS,OAAA;IACP,KAAA;IACA,cAAA;IACA,EAAA;EAAA,MACI,OAAA;EAEN,MAAA,IAAU,OAAA;IACR,KAAA;IACA,cAAA;IACA,IAAA,EAAM,QAAA;IACN,EAAA;IACA,IAAA;EAAA,MACI,OAAA;EAEN,MAAA,IAAU,OAAA;IACR,KAAA;IACA,cAAA;IACA,MAAA,GAAS,MAAA;IACT,OAAA;MAAY,MAAA,GAAS,WAAA;MAAA,CAAc,GAAA;IAAA;EAAA,MAC/B,OAAA;AAAA;AAAA,UAGS,eAAA,cAA6B,OAAA,CAAQ,CAAA,aAAc,OAAA,CAAQ,CAAA;EAC1E,GAAA,EAAK,OAAA,CAAQ,CAAA,EAAG,OAAA,EAAS,OAAA;EACzB,SAAA;EACA,QAAA;EACA,MAAA;EACA,QAAA;IACE,SAAA;IACA,MAAA;IACA,oBAAA;IACA,iBAAA;IACA,QAAA;MACE,aAAA;MACA,WAAA;MACA,aAAA;MACA,WAAA;MACA,aAAA;MACA,WAAA;IAAA;EAAA;EAGJ,SAAA;IACE,QAAA,GAAW,iBAAA,CAAkB,CAAA;MAAK,IAAA,EAAM,OAAA;IAAA;IACxC,QAAA,GAAW,iBAAA,CAAkB,CAAA;MAAK,EAAA;MAAY,IAAA,EAAM,OAAA;IAAA;IACpD,QAAA,GAAW,iBAAA;MAA6B,EAAA;IAAA;EAAA;EAE1C,MAAA,GAAS,SAAA;AAAA;AAAA,UAGM,cAAA;EACf,KAAA;EACA,cAAA;EACA,IAAA,EAAM,KAAA;AAAA;AAAA,UAGS,YAAA,gBAA4B,cAAA,CAAe,KAAA;EAC1D,EAAA;AAAA;AAAA,UAGe,YAAA;EACf,KAAA;EACA,cAAA;EACA,EAAA;AAAA;AAAA,UAGe,WAAA;EACf,SAAA,IAAa,IAAA,EAAM,KAAA;EACnB,OAAA,IAAW,KAAA,EAAO,KAAA;EAClB,SAAA,IAAa,IAAA,EAAM,KAAA,cAAmB,KAAA,EAAO,KAAA;EAC7C,MAAA;AAAA;AAAA,UAGe,WAAA;EACf,MAAA,GAAS,MAAA,EAAQ,cAAA,CAAe,OAAA,GAAU,OAAA,GAAU,WAAA,CAAY,CAAA,MAAO,OAAA,CAAQ,CAAA;EAC/E,MAAA,GAAS,MAAA,EAAQ,YAAA,CAAa,OAAA,GAAU,OAAA,GAAU,WAAA,CAAY,CAAA,MAAO,OAAA,CAAQ,CAAA;EAC7E,MAAA,GAAS,MAAA,EAAQ,YAAA,EAAc,OAAA,GAAU,WAAA,KAAgB,OAAA;EACzD,UAAA;EACA,UAAA;EACA,UAAA;EACA,UAAA;AAAA;AAAA,UAGe,iBAAA;EACf,MAAA;EACA,OAAA;AAAA;AAAA,KAGU,UAAA,OAAiB,IAAA,UAAc,IAAA,EAAM,CAAA,EAAG,OAAA,GAAU,iBAAA;AAAA,UAE7C,eAAA;EACf,IAAA,EAAM,SAAA;EACN,KAAA,EAAO,UAAA,CAAW,CAAA;EAClB,OAAA;IArEA,6EAuEG,MAAA,GAAS,MAAA,mBAAyB,OAAA,GAAU,gBAAA,CAAiB,CAAA,IAAK,eAAA,CAAgB,CAAA,GAvExE;IAAA,CAyEV,KAAA,iBAAsB,MAAA,GAAS,MAAA,mBAAyB,OAAA,GAAU,gBAAA,CAAiB,CAAA,IAAK,eAAA,CAAgB,CAAA;EAAA;EAE3G,SAAA;IAzEA,uEA2EG,EAAA,iBAAmB,OAAA,GAAU,kBAAA,CAAmB,CAAA,IAAK,iBAAA,CAAkB,CAAA,GAzE1E;IAAA,CA2EG,EAAA,iBAAmB,KAAA,iBAAsB,OAAA,GAAU,kBAAA,CAAmB,CAAA,IAAK,iBAAA,CAAkB,CAAA;EAAA;EAEhG,eAAA;IAzEE,6EA2EC,MAAA,GAAS,MAAA,mBAAyB,OAAA,GAAU,wBAAA,GAA2B,uBAAA,CAAwB,CAAA,GAzE9F;IAAA,CA2ED,KAAA,iBAAsB,MAAA,GAAS,MAAA,mBAAyB,OAAA,GAAU,wBAAA,GAA2B,uBAAA,CAAwB,CAAA;EAAA;EAExH,UAAA,QAAkB,WAAA,CAAY,CAAA,EAAG,OAAA,EAAS,OAAA;EAC1C,SAAA,GAAY,OAAA;IACV,iBAAA,GAAoB,QAAA;IACpB,QAAA,GAAW,gBAAA;IACX,SAAA,IAAa,IAAA;IACb,OAAA,IAAW,KAAA,EAAO,KAAA;IAClB,SAAA,IAAa,IAAA,uBAA2B,KAAA,EAAO,KAAA;EAAA,MAC3C,wBAAA;IAAoC,IAAA,EAAM,QAAA;IAAU,EAAA;IAAa,IAAA;EAAA;EACvE,SAAA,GAAY,KAAA,UAAe,MAAA,GAAS,MAAA,mBAAyB,OAAA,GAAU,gBAAA,CAAiB,CAAA,MAAO,eAAA,CAAgB,CAAA;EAC/G,iBAAA,0CAA2D,MAAA;IACzD,UAAA,GAAa,SAAA,EAAW,UAAA,KAAe,OAAA,CAAQ,KAAA;IAC/C,iBAAA,GAAoB,QAAA;IACpB,QAAA,GAAW,gBAAA;IACX,SAAA,IAAa,IAAA,EAAM,KAAA,EAAO,SAAA,EAAW,UAAA;IACrC,OAAA,IAAW,KAAA,EAAO,KAAA,EAAO,SAAA,EAAW,UAAA;IACpC,SAAA,IAAa,IAAA,EAAM,KAAA,cAAmB,KAAA,EAAO,KAAA,SAAc,SAAA,EAAW,UAAA;EAAA,MAClE,wBAAA,CAAyB,KAAA,EAAO,UAAA;EACtC,aAAA,QAAqB,UAAA,CAAW,CAAA;AAAA;;;;;;;;iBAgBlB,mBAAA,CAAoB,IAAA,EAAM,aAAA;AAAA,iBAqB1B,eAAA,cAA6B,OAAA,CAAQ,CAAA,aAAc,OAAA,CAAQ,CAAA,EAAA,CAAA;EACzE,GAAA;EACA,SAAA;EACA,QAAA;EACA,QAAA;EACA,SAAA;EACA;AAAA,GACC,eAAA,CAAgB,CAAA,EAAG,OAAA,EAAS,OAAA,IAAW,eAAA,CAAgB,CAAA,EAAG,OAAA,EAAS,OAAA"}
package/dist/hooks.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"hooks.js","names":[],"sources":["../src/hooks.ts"],"sourcesContent":["\"use client\";\n\nimport { useQueryClient, useMutation, type QueryKey } from \"@tanstack/react-query\";\nimport { useCallback, useRef } from \"react\";\nimport { createOptimisticMutation, useMutationWithTransition } from \"./mutation.js\";\nimport type { MutationMessages } from \"./mutation.js\";\nimport {\n createListQuery,\n createDetailQuery,\n createInfiniteListQuery,\n updateListCache,\n getItemId,\n createQueryKeys,\n createCacheUtils,\n DEFAULT_QUERY_CONFIG,\n} from \"./query.js\";\nimport type {\n QueryKeys,\n CacheUtils,\n ListQueryOptions,\n DetailQueryOptions,\n ListQueryResult,\n DetailQueryResult,\n InfiniteListQueryOptions,\n InfiniteListQueryResult,\n} from \"./query.js\";\nimport {\n isOffsetPagination,\n isKeysetPagination,\n} from \"./api.js\";\nimport type { PaginatedResponse } from \"./api.js\";\nimport type { MutationCallbacks, TransitionMutationReturn } from \"./mutation.js\";\nimport { getAuthMode, getAuthContext } from \"./client.js\";\nimport type { ArcClient, ToastHandler, UseRouterHook } from \"./client.js\";\n\n// Re-export UseRouterHook for backward compatibility\nexport type { UseRouterHook } from \"./client.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface CrudApi<T, TCreate = Partial<T>, TUpdate = Partial<T>> {\n getAll: (options: {\n token?: string | null;\n organizationId?: string | null;\n params?: Record<string, unknown>;\n options?: { signal?: AbortSignal; [key: string]: unknown };\n }) => Promise<unknown>;\n\n getById: (options: {\n id: string;\n token?: string | null;\n organizationId?: string | null;\n params?: { select?: string; populate?: string | string[] };\n options?: { signal?: AbortSignal; [key: string]: unknown };\n }) => Promise<unknown>;\n\n create: (options: {\n token?: string | null;\n organizationId?: string | null;\n data: TCreate;\n }) => Promise<unknown>;\n\n update: (options: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n data: TUpdate;\n }) => Promise<unknown>;\n\n delete: (options: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n }) => Promise<unknown>;\n\n upload?: (options: {\n token?: string | null;\n organizationId?: string | null;\n data: FormData;\n id?: string;\n path?: string;\n }) => Promise<unknown>;\n\n search?: (options: {\n token?: string | null;\n organizationId?: string | null;\n params?: Record<string, unknown>;\n options?: { signal?: AbortSignal; [key: string]: unknown };\n }) => Promise<unknown>;\n}\n\nexport interface CrudHooksConfig<T, TCreate = Partial<T>, TUpdate = Partial<T>> {\n api: CrudApi<T, TCreate, TUpdate>;\n entityKey: string;\n singular: string;\n plural?: string;\n defaults?: {\n staleTime?: number;\n gcTime?: number;\n refetchOnWindowFocus?: boolean;\n structuralSharing?: boolean;\n messages?: {\n createSuccess?: string;\n createError?: string;\n updateSuccess?: string;\n updateError?: string;\n deleteSuccess?: string;\n deleteError?: string;\n };\n };\n callbacks?: {\n onCreate?: MutationCallbacks<T, { data: TCreate }>;\n onUpdate?: MutationCallbacks<T, { id: string; data: TUpdate }>;\n onDelete?: MutationCallbacks<unknown, { id: string }>;\n };\n client?: ArcClient;\n}\n\nexport interface MutationParams<TData> {\n token?: string | null;\n organizationId?: string | null;\n data: TData;\n}\n\nexport interface UpdateParams<TData> extends MutationParams<TData> {\n id: string;\n}\n\nexport interface DeleteParams {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n}\n\nexport interface CallOptions<TData = unknown> {\n onSuccess?: (data: TData) => void;\n onError?: (error: Error) => void;\n onSettled?: (data: TData | undefined, error: Error | null) => void;\n silent?: boolean;\n}\n\nexport interface CrudActions<T, TCreate, TUpdate> {\n create: (params: MutationParams<TCreate>, options?: CallOptions<T>) => Promise<T>;\n update: (params: UpdateParams<TUpdate>, options?: CallOptions<T>) => Promise<T>;\n remove: (params: DeleteParams, options?: CallOptions) => Promise<unknown>;\n isCreating: boolean;\n isUpdating: boolean;\n isDeleting: boolean;\n isMutating: boolean;\n}\n\nexport interface NavigationOptions {\n scroll?: boolean;\n replace?: boolean;\n}\n\nexport type NavigateFn<T> = (href: string, item: T, options?: NavigationOptions) => void;\n\nexport interface CrudHooksReturn<T, TCreate, TUpdate> {\n KEYS: QueryKeys;\n cache: CacheUtils<T>;\n useList: {\n /** New signature — auto-injects token/orgId from configureAuth() context */\n (params?: Record<string, unknown>, options?: ListQueryOptions<T>): ListQueryResult<T>;\n /** Legacy signature — explicit token */\n (token: string | null, params?: Record<string, unknown>, options?: ListQueryOptions<T>): ListQueryResult<T>;\n };\n useDetail: {\n /** New signature — auto-injects token from configureAuth() context */\n (id: string | null, options?: DetailQueryOptions<T>): DetailQueryResult<T>;\n /** Legacy signature — explicit token */\n (id: string | null, token: string | null, options?: DetailQueryOptions<T>): DetailQueryResult<T>;\n };\n useInfiniteList: {\n /** New signature — auto-injects token/orgId from configureAuth() context */\n (params?: Record<string, unknown>, options?: InfiniteListQueryOptions): InfiniteListQueryResult<T>;\n /** Legacy signature — explicit token */\n (token: string | null, params?: Record<string, unknown>, options?: InfiniteListQueryOptions): InfiniteListQueryResult<T>;\n };\n useActions: () => CrudActions<T, TCreate, TUpdate>;\n useUpload: (options?: {\n invalidateQueries?: QueryKey[];\n messages?: MutationMessages;\n onSuccess?: (data: unknown) => void;\n onError?: (error: Error) => void;\n onSettled?: (data: unknown | undefined, error: Error | null) => void;\n }) => TransitionMutationReturn<unknown, { data: FormData; id?: string; path?: string }>;\n useSearch: (query: string, params?: Record<string, unknown>, options?: ListQueryOptions<T>) => ListQueryResult<T>;\n useCustomMutation: <TData = unknown, TVariables = unknown>(config: {\n mutationFn: (variables: TVariables) => Promise<TData>;\n invalidateQueries?: QueryKey[];\n messages?: MutationMessages;\n onSuccess?: (data: TData, variables: TVariables) => void;\n onError?: (error: Error, variables: TVariables) => void;\n onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;\n }) => TransitionMutationReturn<TData, TVariables>;\n useNavigation: () => NavigateFn<T>;\n}\n\n// ============================================================================\n// Navigation Configuration (Global)\n// ============================================================================\n\nlet useRouterHook: UseRouterHook | null = null;\n\n/**\n * Configure the router hook for useNavigation. Call once at app init.\n *\n * @example\n * import { useRouter } from \"next/navigation\";\n * configureNavigation(useRouter);\n */\nexport function configureNavigation(hook: UseRouterHook): void {\n useRouterHook = hook;\n}\n\n// ============================================================================\n// Enabled Rule\n// ============================================================================\n\nfunction createEnabledRule(token: string | null, options: { public?: boolean; enabled?: boolean }): boolean {\n // Cookie-based auth: no token needed, queries always enabled (cookies sent via credentials: 'include')\n if (getAuthMode() === 'cookie' || options.public) {\n return options.enabled ?? true;\n }\n // Bearer token auth: require token to enable queries\n return options.enabled !== undefined ? options.enabled && !!token : !!token;\n}\n\n// ============================================================================\n// Create CRUD Hooks Factory\n// ============================================================================\n\nexport function createCrudHooks<T, TCreate = Partial<T>, TUpdate = Partial<T>>({\n api,\n entityKey,\n singular,\n defaults = {},\n callbacks = {},\n client,\n}: CrudHooksConfig<T, TCreate, TUpdate>): CrudHooksReturn<T, TCreate, TUpdate> {\n const KEYS = createQueryKeys(entityKey);\n const cache = createCacheUtils<T>(KEYS);\n\n // Resolve toast handler: client instance → global\n const instanceToast: ToastHandler | undefined = client?.toast;\n // Resolve navigation hook: client instance → global\n const instanceNavigation: UseRouterHook | null = client?.navigation ?? null;\n\n const config = {\n ...DEFAULT_QUERY_CONFIG,\n ...defaults,\n structuralSharing: defaults.structuralSharing,\n messages: {\n createSuccess: `${singular} created successfully`,\n createError: `Failed to create ${singular.toLowerCase()}`,\n updateSuccess: `${singular} updated successfully`,\n updateError: `Failed to update ${singular.toLowerCase()}`,\n deleteSuccess: `${singular} deleted successfully`,\n deleteError: `Failed to delete ${singular.toLowerCase()}`,\n ...defaults.messages,\n },\n };\n\n // ========== useList ==========\n\n function useList(\n tokenOrParams?: string | null | Record<string, unknown>,\n paramsOrOptions?: Record<string, unknown> | ListQueryOptions,\n maybeOptions?: ListQueryOptions,\n ): ListQueryResult<T> {\n let token: string | null;\n let params: Record<string, unknown>;\n let options: ListQueryOptions;\n\n // Detect which overload: first arg is string|null = legacy, object/undefined = new\n if (tokenOrParams === null || typeof tokenOrParams === 'string') {\n token = tokenOrParams;\n params = (paramsOrOptions as Record<string, unknown>) ?? {};\n options = maybeOptions ?? {};\n } else {\n const auth = getAuthContext();\n token = auth.token;\n params = (tokenOrParams as Record<string, unknown>) ?? {};\n options = (paramsOrOptions as ListQueryOptions) ?? {};\n if (auth.organizationId && !params.organizationId) {\n params = { ...params, organizationId: auth.organizationId };\n }\n }\n\n const { organizationId, ...restParams } = params;\n const scope = options._scope || (organizationId ? \"tenant\" : \"super-admin\");\n const { request: requestOpts, ...queryOpts } = options;\n\n return createListQuery<T>({\n queryKey: KEYS.scopedList(scope, { organizationId, ...restParams }),\n queryFn: ({ signal }) => api.getAll({ token, organizationId: organizationId as string | null, params: restParams, options: { signal, ...requestOpts } }),\n enabled: createEnabledRule(token, queryOpts),\n options: {\n staleTime: queryOpts.staleTime ?? config.staleTime,\n gcTime: queryOpts.gcTime ?? config.gcTime,\n refetchOnWindowFocus: queryOpts.refetchOnWindowFocus ?? config.refetchOnWindowFocus,\n structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing,\n refetchInterval: queryOpts.refetchInterval,\n refetchIntervalInBackground: queryOpts.refetchIntervalInBackground,\n },\n prefillDetailCache: queryOpts.prefillDetailCache ?? true,\n detailKeyBuilder: (id) => KEYS.detail(id),\n select: queryOpts.select,\n });\n }\n\n // ========== useDetail ==========\n\n function useDetail(\n id: string | null,\n tokenOrOptions?: string | null | DetailQueryOptions,\n maybeOptions?: DetailQueryOptions,\n ): DetailQueryResult<T> {\n let token: string | null;\n let options: DetailQueryOptions;\n\n // Detect which overload: second arg is string|null = legacy, object/undefined = new\n if (tokenOrOptions === null || typeof tokenOrOptions === 'string') {\n token = tokenOrOptions;\n options = maybeOptions ?? {};\n } else {\n const auth = getAuthContext();\n token = auth.token;\n options = (tokenOrOptions as DetailQueryOptions) ?? {};\n if (auth.organizationId && !options.organizationId) {\n options = { ...options, organizationId: auth.organizationId };\n }\n }\n\n const { organizationId, params: queryParams, request: requestOpts, ...restOptions } = options;\n\n return createDetailQuery<T>({\n queryKey: queryParams ? [...KEYS.detail(id || \"\"), queryParams] : KEYS.detail(id || \"\"),\n queryFn: ({ signal }) => api.getById({ id: id!, token, organizationId, params: queryParams, options: { signal, ...requestOpts } }),\n enabled: !!id && createEnabledRule(token, restOptions),\n options: {\n staleTime: restOptions.staleTime ?? config.staleTime,\n gcTime: restOptions.gcTime ?? config.gcTime,\n structuralSharing: restOptions.structuralSharing ?? config.structuralSharing,\n refetchInterval: restOptions.refetchInterval,\n refetchIntervalInBackground: restOptions.refetchIntervalInBackground,\n },\n select: restOptions.select,\n });\n }\n\n // ========== useActions ==========\n\n function useActions(): CrudActions<T, TCreate, TUpdate> {\n const queryClient = useQueryClient();\n const silentRef = useRef(false);\n const shouldToast = useCallback(() => !silentRef.current, []);\n\n const createMutation = createOptimisticMutation({\n mutationFn: ({ token, organizationId, data }: MutationParams<TCreate>) =>\n api.create({ token, organizationId, data }),\n queryClient,\n queryKeys: [KEYS.lists()],\n shouldToast,\n optimisticUpdate: (oldData, { data }) => {\n const optimisticItem = {\n ...(data as object),\n _optimistic: true,\n [getItemId(data) ? \"id\" : \"_id\"]: getItemId(data) ?? `temp-${Date.now()}`,\n };\n return updateListCache(oldData, (arr: unknown[]) => [optimisticItem, ...(arr || [])]);\n },\n onSuccess: (data, variables) => {\n callbacks.onCreate?.onSuccess?.(data as T, { data: variables.data }, undefined);\n },\n onError: (error, variables) => {\n callbacks.onCreate?.onError?.(error, { data: variables.data }, undefined);\n },\n onSettled: (data, error, variables) => {\n callbacks.onCreate?.onSettled?.(data as T | undefined, error, { data: variables.data }, undefined);\n },\n messages: { success: config.messages.createSuccess, error: config.messages.createError },\n toastHandler: instanceToast,\n });\n\n const updateMutation = createOptimisticMutation({\n mutationFn: ({ token, organizationId, id, data }: UpdateParams<TUpdate>) =>\n api.update({ token, organizationId, id, data }),\n queryClient,\n queryKeys: [KEYS.lists()],\n shouldToast,\n optimisticUpdate: (oldData, { id, data }) => {\n const updated = updateListCache(oldData, (arr: unknown[]) =>\n (arr || []).map((item) => (getItemId(item) === id ? { ...(item as object), ...(data as object) } : item))\n );\n queryClient.setQueryData(KEYS.detail(id), (current: unknown) =>\n current ? { ...(current as object), data: { ...((current as { data?: object }).data || {}), ...(data as object) } } : current\n );\n return updated;\n },\n onSuccess: (data, { id, data: updateData }) => {\n queryClient.invalidateQueries({ queryKey: KEYS.detail(id) });\n callbacks.onUpdate?.onSuccess?.(data as T, { id, data: updateData }, undefined);\n },\n onError: (error, { id, data }) => {\n callbacks.onUpdate?.onError?.(error, { id, data }, undefined);\n },\n onSettled: (data, error, { id, data: updateData }) => {\n callbacks.onUpdate?.onSettled?.(data as T | undefined, error, { id, data: updateData }, undefined);\n },\n messages: { success: config.messages.updateSuccess, error: config.messages.updateError },\n toastHandler: instanceToast,\n });\n\n const deleteMutation = createOptimisticMutation({\n mutationFn: ({ token, organizationId, id }: DeleteParams) => api.delete({ token, organizationId, id }),\n queryClient,\n queryKeys: [KEYS.lists()],\n shouldToast,\n optimisticUpdate: (oldData, { id }) => {\n queryClient.removeQueries({ queryKey: KEYS.detail(id) });\n return updateListCache(oldData, (arr: unknown[]) => (arr || []).filter((item) => getItemId(item) !== id));\n },\n onSuccess: (data, { id }) => {\n callbacks.onDelete?.onSuccess?.(data, { id }, undefined);\n },\n onError: (error, { id }) => {\n callbacks.onDelete?.onError?.(error, { id }, undefined);\n },\n onSettled: (data, error, { id }) => {\n callbacks.onDelete?.onSettled?.(data, error, { id }, undefined);\n },\n messages: { success: config.messages.deleteSuccess, error: config.messages.deleteError },\n toastHandler: instanceToast,\n });\n\n const resolveAuth = <P extends { token?: string | null; organizationId?: string | null }>(params: P): P => {\n const auth = getAuthContext();\n return {\n ...params,\n token: params.token ?? auth.token,\n organizationId: params.organizationId ?? auth.organizationId,\n };\n };\n\n const create = async (params: MutationParams<TCreate>, options?: CallOptions<T>): Promise<T> => {\n silentRef.current = options?.silent ?? false;\n try {\n const result = await createMutation.mutateAsync(resolveAuth(params));\n options?.onSuccess?.(result as T);\n options?.onSettled?.(result as T, null);\n return result as T;\n } catch (error) {\n options?.onError?.(error as Error);\n options?.onSettled?.(undefined, error as Error);\n throw error;\n } finally {\n silentRef.current = false;\n }\n };\n\n const update = async (params: UpdateParams<TUpdate>, options?: CallOptions<T>): Promise<T> => {\n silentRef.current = options?.silent ?? false;\n try {\n const result = await updateMutation.mutateAsync(resolveAuth(params));\n options?.onSuccess?.(result as T);\n options?.onSettled?.(result as T, null);\n return result as T;\n } catch (error) {\n options?.onError?.(error as Error);\n options?.onSettled?.(undefined, error as Error);\n throw error;\n } finally {\n silentRef.current = false;\n }\n };\n\n const remove = async (params: DeleteParams, options?: CallOptions): Promise<unknown> => {\n silentRef.current = options?.silent ?? false;\n try {\n const result = await deleteMutation.mutateAsync(resolveAuth(params));\n options?.onSuccess?.(result);\n options?.onSettled?.(result, null);\n return result;\n } catch (error) {\n options?.onError?.(error as Error);\n options?.onSettled?.(undefined, error as Error);\n throw error;\n } finally {\n silentRef.current = false;\n }\n };\n\n return {\n create,\n update,\n remove,\n isCreating: createMutation.isPending,\n isUpdating: updateMutation.isPending,\n isDeleting: deleteMutation.isPending,\n isMutating: createMutation.isPending || updateMutation.isPending || deleteMutation.isPending,\n };\n }\n\n // ========== useInfiniteList ==========\n\n function useInfiniteList(\n tokenOrParams?: string | null | Record<string, unknown>,\n paramsOrOptions?: Record<string, unknown> | InfiniteListQueryOptions,\n maybeOptions?: InfiniteListQueryOptions,\n ): InfiniteListQueryResult<T> {\n let token: string | null;\n let params: Record<string, unknown>;\n let options: InfiniteListQueryOptions;\n\n if (tokenOrParams === null || typeof tokenOrParams === 'string') {\n token = tokenOrParams;\n params = (paramsOrOptions as Record<string, unknown>) ?? {};\n options = maybeOptions ?? {};\n } else {\n const auth = getAuthContext();\n token = auth.token;\n params = (tokenOrParams as Record<string, unknown>) ?? {};\n options = (paramsOrOptions as InfiniteListQueryOptions) ?? {};\n if (auth.organizationId && !params.organizationId) {\n params = { ...params, organizationId: auth.organizationId };\n }\n }\n\n const { organizationId, ...restParams } = params;\n const scope = options._scope || (organizationId ? \"tenant\" : \"super-admin\");\n const { request: requestOpts, ...queryOpts } = options;\n\n return createInfiniteListQuery<T>({\n queryKey: [...KEYS.scopedList(scope, { organizationId, ...restParams }), 'infinite'],\n queryFn: ({ pageParam, signal }) => {\n const paginationParams = typeof pageParam === 'string'\n ? { after: pageParam }\n : { page: pageParam };\n\n return api.getAll({\n token,\n organizationId: organizationId as string | null,\n params: { ...restParams, ...paginationParams },\n options: { signal, ...requestOpts },\n });\n },\n enabled: createEnabledRule(token, queryOpts),\n initialPageParam: restParams.after ? restParams.after : 1,\n getNextPageParam: (lastPage) => {\n const page = lastPage as PaginatedResponse<T>;\n if (isKeysetPagination(page)) {\n return page.hasMore ? page.next : undefined;\n }\n if (isOffsetPagination(page)) {\n return page.hasNext ? page.page + 1 : undefined;\n }\n // Fallback: check common pagination fields\n const p = page as unknown as Record<string, unknown>;\n if (typeof p.hasNext === 'boolean' && typeof p.page === 'number') {\n return p.hasNext ? (p.page as number) + 1 : undefined;\n }\n return undefined;\n },\n options: {\n staleTime: queryOpts.staleTime ?? config.staleTime,\n gcTime: queryOpts.gcTime ?? config.gcTime,\n refetchOnWindowFocus: queryOpts.refetchOnWindowFocus ?? config.refetchOnWindowFocus,\n structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing,\n },\n });\n }\n\n // ========== useUpload ==========\n\n function useUpload(options?: {\n invalidateQueries?: QueryKey[];\n messages?: MutationMessages;\n onSuccess?: (data: unknown) => void;\n onError?: (error: Error) => void;\n onSettled?: (data: unknown | undefined, error: Error | null) => void;\n }) {\n if (!api.upload) {\n throw new Error(`[arc-next] \"${entityKey}\" api does not define an upload method`);\n }\n\n const uploadApi = api.upload;\n\n return useMutationWithTransition<unknown, { data: FormData; id?: string; path?: string }>({\n mutationFn: ({ data, id, path }) => {\n const auth = getAuthContext();\n return uploadApi({ token: auth.token, organizationId: auth.organizationId, data, id, path });\n },\n invalidateQueries: options?.invalidateQueries ?? [KEYS.lists()],\n onSuccess: (data) => options?.onSuccess?.(data),\n onError: (error) => options?.onError?.(error),\n onSettled: (data, error) => options?.onSettled?.(data, error),\n messages: options?.messages ?? {\n success: `${singular} uploaded successfully`,\n error: `Failed to upload ${singular.toLowerCase()}`,\n },\n toastHandler: instanceToast,\n });\n }\n\n // ========== useSearch ==========\n\n function useSearch(\n query: string,\n params?: Record<string, unknown>,\n options?: ListQueryOptions<T>,\n ): ListQueryResult<T> {\n if (!api.search) {\n throw new Error(`[arc-next] \"${entityKey}\" api does not define a search method`);\n }\n\n const searchApi = api.search;\n const auth = getAuthContext();\n const token = auth.token;\n const organizationId = params?.organizationId as string | null ?? auth.organizationId;\n const { organizationId: _, ...restParams } = params ?? {};\n const searchParams = { q: query, ...restParams };\n const { request: requestOpts, ...queryOpts } = options ?? {};\n\n // Include organizationId in query key when present to isolate per-tenant search cache\n const searchKeyParams = organizationId\n ? { organizationId, ...searchParams }\n : searchParams;\n\n return createListQuery<T>({\n queryKey: [...KEYS.lists(), 'search', searchKeyParams],\n queryFn: ({ signal }) => searchApi({\n token,\n organizationId,\n params: searchParams,\n options: { signal, ...requestOpts },\n }),\n enabled: query.length > 0 && createEnabledRule(token, queryOpts),\n options: {\n staleTime: queryOpts.staleTime ?? config.staleTime,\n gcTime: queryOpts.gcTime ?? config.gcTime,\n },\n select: queryOpts.select,\n });\n }\n\n // ========== useCustomMutation ==========\n\n function useCustomMutation<TData = unknown, TVariables = unknown>(mutationConfig: {\n mutationFn: (variables: TVariables) => Promise<TData>;\n invalidateQueries?: QueryKey[];\n messages?: MutationMessages;\n onSuccess?: (data: TData, variables: TVariables) => void;\n onError?: (error: Error, variables: TVariables) => void;\n onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;\n }) {\n return useMutationWithTransition<TData, TVariables>({\n mutationFn: mutationConfig.mutationFn,\n invalidateQueries: mutationConfig.invalidateQueries ?? [KEYS.lists()],\n onSuccess: mutationConfig.onSuccess,\n onError: mutationConfig.onError,\n onSettled: mutationConfig.onSettled,\n messages: mutationConfig.messages,\n toastHandler: instanceToast,\n });\n }\n\n // ========== useNavigation ==========\n\n function useNavigation(): NavigateFn<T> {\n const queryClient = useQueryClient();\n const activeRouterHook = instanceNavigation ?? useRouterHook;\n const router = activeRouterHook?.();\n\n return useCallback(\n (href: string, item: T, options: NavigationOptions = {}) => {\n const id = getItemId(item);\n if (id) {\n queryClient.setQueryData(KEYS.detail(id), { data: item });\n }\n\n if (!router) return;\n\n const { scroll = true, replace = false } = options;\n if (replace) {\n router.replace(href, { scroll });\n } else {\n router.push(href, { scroll });\n }\n },\n [queryClient, router]\n );\n }\n\n return {\n KEYS,\n cache,\n useList,\n useDetail,\n useInfiniteList,\n useActions,\n useUpload,\n useSearch,\n useCustomMutation,\n useNavigation,\n };\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"mutation.d.ts","names":[],"sources":["../src/mutation.ts"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"mutation.js","names":[],"sources":["../src/mutation.ts"],"sourcesContent":["\"use client\";\n\nimport { useMutation, useQueryClient, type QueryClient, type QueryKey, type UseMutateFunction, type UseMutateAsyncFunction } from \"@tanstack/react-query\";\nimport { useTransition } from \"react\";\nimport { isArcApiError } from \"./client.js\";\nimport type { ToastHandler } from \"./client.js\";\n\n// Re-export for backward compatibility\nexport type { ToastHandler } from \"./client.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface MutationMessages {\n success?: string | ((data: unknown, variables: unknown) => string);\n error?: string | ((error: Error, variables: unknown) => string);\n}\n\nexport interface MutationCallbacks<TData, TVariables, TContext = unknown> {\n onMutate?: (variables: TVariables) => TContext | Promise<TContext>;\n onSuccess?: (data: TData, variables: TVariables, context: TContext) => void | Promise<void>;\n onError?: (error: Error, variables: TVariables, context: TContext) => void | Promise<void>;\n onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables, context: TContext) => void | Promise<void>;\n}\n\nexport interface TransitionMutationReturn<TData, TVariables> {\n mutate: UseMutateFunction<TData, Error, TVariables>;\n mutateAsync: UseMutateAsyncFunction<TData, Error, TVariables>;\n isPending: boolean;\n isSuccess: boolean;\n isError: boolean;\n error: Error | null;\n data: TData | undefined;\n reset: () => void;\n}\n\n// ============================================================================\n// Toast Configuration\n// ============================================================================\n\nlet toastHandler: ToastHandler = {\n success: (msg) => console.log(\"[Success]\", msg),\n error: (msg) => console.error(\"[Error]\", msg),\n};\n\n/**\n * Configure toast handler. Call once at app init.\n *\n * @example\n * import { toast } from \"sonner\";\n * configureToast({ success: toast.success, error: toast.error });\n */\nexport function configureToast(handler: ToastHandler): void {\n toastHandler = handler;\n}\n\nfunction showToast(\n type: \"success\" | \"error\",\n messages: MutationMessages | undefined,\n data: unknown,\n variables: unknown,\n error?: Error,\n handler?: ToastHandler,\n) {\n const activeHandler = handler ?? toastHandler;\n\n if (type === \"success\") {\n const msg = messages?.success;\n if (!msg) return;\n\n const text = typeof msg === \"function\" ? msg(data, variables) : msg;\n activeHandler.success(text);\n } else {\n const msg = messages?.error;\n let defaultMsg = error?.message || \"An error occurred\";\n if (isArcApiError(error) && error.fieldErrors) {\n const fields = Object.entries(error.fieldErrors);\n if (fields.length > 0) {\n defaultMsg = fields.map(([k, v]) => `${k}: ${v}`).join(', ');\n }\n }\n const text = typeof msg === \"function\"\n ? msg(error as Error, variables)\n : msg || defaultMsg;\n\n activeHandler.error(text);\n }\n}\n\n// ============================================================================\n// Mutation with React 19 Transitions\n// ============================================================================\n\nexport interface TransitionMutationConfig<TData, TVariables> {\n mutationFn: (variables: TVariables) => Promise<TData>;\n invalidateQueries?: QueryKey[];\n onSuccess?: (data: TData, variables: TVariables) => void;\n onError?: (error: Error, variables: TVariables) => void;\n onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;\n messages?: MutationMessages;\n useTransition?: boolean;\n showToast?: boolean;\n /** Per-call toast guard — return false to suppress toast for this invocation */\n shouldToast?: () => boolean;\n toastHandler?: ToastHandler;\n}\n\nexport function useMutationWithTransition<TData, TVariables>(config: TransitionMutationConfig<TData, TVariables>) {\n const {\n mutationFn,\n invalidateQueries = [],\n onSuccess,\n onError,\n onSettled,\n messages,\n useTransition: withTransition = true,\n showToast: toast = true,\n toastHandler: instanceToast,\n } = config;\n\n const queryClient = useQueryClient();\n const [isTransitioning, startTransition] = useTransition();\n\n const mutation = useMutation({\n mutationFn,\n\n onSuccess: (data, variables) => {\n const invalidate = () => {\n invalidateQueries.forEach((key) => queryClient.invalidateQueries({ queryKey: key }));\n };\n\n if (withTransition && invalidateQueries.length > 0) {\n startTransition(invalidate);\n } else {\n invalidate();\n }\n\n const doToast = toast && (config.shouldToast?.() ?? true);\n if (doToast) showToast(\"success\", messages, data, variables, undefined, instanceToast);\n onSuccess?.(data, variables);\n },\n\n onError: (error, variables) => {\n const doToast = toast && (config.shouldToast?.() ?? true);\n if (doToast) showToast(\"error\", messages, null, variables, error as Error, instanceToast);\n onError?.(error as Error, variables);\n },\n\n onSettled: (data, error, variables) => {\n onSettled?.(data, error as Error | null, variables);\n },\n });\n\n return {\n mutate: mutation.mutate,\n mutateAsync: mutation.mutateAsync,\n isPending: mutation.isPending || isTransitioning,\n isSuccess: mutation.isSuccess,\n isError: mutation.isError,\n error: mutation.error as Error | null,\n data: mutation.data,\n reset: mutation.reset,\n };\n}\n\n// ============================================================================\n// Mutation with Optimistic Updates\n// ============================================================================\n\nexport interface OptimisticMutationConfig<TData, TVariables> {\n mutationFn: (variables: TVariables) => Promise<TData>;\n queryKeys?: QueryKey[];\n optimisticUpdate?: (oldData: unknown, variables: TVariables) => unknown;\n onSuccess?: (data: TData, variables: TVariables) => void;\n onError?: (error: Error, variables: TVariables) => void;\n onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;\n messages?: MutationMessages;\n showToast?: boolean;\n toastHandler?: ToastHandler;\n}\n\nexport function useMutationWithOptimistic<TData, TVariables>(config: OptimisticMutationConfig<TData, TVariables>) {\n const {\n mutationFn,\n queryKeys = [],\n optimisticUpdate,\n onSuccess,\n onError,\n onSettled,\n messages,\n showToast: toast = true,\n toastHandler: instanceToast,\n } = config;\n\n const queryClient = useQueryClient();\n\n const mutation = useMutation({\n mutationFn,\n\n onMutate: async (variables) => {\n await Promise.all(queryKeys.map((key) => queryClient.cancelQueries({ queryKey: key })));\n\n const previous = queryKeys.map((key) => ({\n key,\n data: queryClient.getQueryData(key),\n }));\n\n if (optimisticUpdate) {\n queryKeys.forEach((key) => {\n queryClient.setQueryData(key, (old: unknown) => optimisticUpdate(old, variables));\n });\n }\n\n return { previous };\n },\n\n onSuccess: (data, variables) => {\n queryKeys.forEach((key) => queryClient.invalidateQueries({ queryKey: key }));\n if (toast) showToast(\"success\", messages, data, variables, undefined, instanceToast);\n onSuccess?.(data, variables);\n },\n\n onError: (error, variables, context) => {\n const ctx = context as { previous?: Array<{ key: QueryKey; data: unknown }> };\n ctx?.previous?.forEach(({ key, data }) => queryClient.setQueryData(key, data));\n\n if (toast) showToast(\"error\", messages, null, variables, error as Error, instanceToast);\n onError?.(error as Error, variables);\n },\n\n onSettled: (data, error, variables) => {\n onSettled?.(data, error as Error | null, variables);\n },\n });\n\n return {\n mutate: mutation.mutate,\n mutateAsync: mutation.mutateAsync,\n isPending: mutation.isPending,\n isSuccess: mutation.isSuccess,\n isError: mutation.isError,\n error: mutation.error as Error | null,\n data: mutation.data,\n reset: mutation.reset,\n };\n}\n\n// ============================================================================\n// Optimistic Mutation for CRUD Factory (handles multiple matching queries)\n// ============================================================================\n\nexport interface CreateOptimisticMutationConfig<TData, TVariables> {\n mutationFn: (variables: TVariables) => Promise<TData>;\n queryClient: QueryClient;\n queryKeys: QueryKey[];\n optimisticUpdate?: (oldData: unknown, variables: TVariables) => unknown;\n onSuccess?: (data: TData, variables: TVariables) => void;\n onError?: (error: Error, variables: TVariables) => void;\n onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;\n messages?: MutationMessages;\n /** Per-call toast guard — return false to suppress toast for this invocation */\n shouldToast?: () => boolean;\n toastHandler?: ToastHandler;\n}\n\nexport function createOptimisticMutation<TData, TVariables>(config: CreateOptimisticMutationConfig<TData, TVariables>) {\n const {\n mutationFn,\n queryClient,\n queryKeys,\n optimisticUpdate,\n onSuccess,\n onError,\n onSettled,\n messages,\n toastHandler: instanceToast,\n } = config;\n return useMutation({\n mutationFn,\n\n onMutate: async (variables) => {\n await Promise.all(queryKeys.map((key) => queryClient.cancelQueries({ queryKey: key, exact: false })));\n\n const previous = queryKeys.map((key) => ({\n key,\n data: queryClient.getQueriesData({ queryKey: key }),\n }));\n\n if (optimisticUpdate) {\n queryKeys.forEach((key) => {\n queryClient.getQueriesData({ queryKey: key }).forEach(([qKey, qData]) => {\n queryClient.setQueryData(qKey, optimisticUpdate(qData, variables));\n });\n });\n }\n\n return { previous };\n },\n\n onSuccess: (data, variables) => {\n const doToast = config.shouldToast?.() ?? true;\n if (doToast && messages?.success) showToast(\"success\", messages, data, variables, undefined, instanceToast);\n queryKeys.forEach((key) => queryClient.invalidateQueries({ queryKey: key }));\n onSuccess?.(data, variables);\n },\n\n onError: (error, variables, context) => {\n const ctx = context as { previous?: Array<{ key: QueryKey; data: Array<[QueryKey, unknown]> }> };\n ctx?.previous?.forEach(({ data }) => {\n data.forEach(([qKey, qData]) => queryClient.setQueryData(qKey, qData));\n });\n\n const doToast = config.shouldToast?.() ?? true;\n if (doToast) showToast(\"error\", messages, null, variables, error as Error, instanceToast);\n onError?.(error as Error, variables);\n },\n\n onSettled: (data, error, variables) => {\n onSettled?.(data, error as Error | null, variables);\n },\n });\n}\n\n// ============================================================================\n// Query Config Presets\n// ============================================================================\n\nexport const QUERY_CONFIGS = {\n realtime: { staleTime: 20_000, refetchInterval: 30_000 },\n frequent: { staleTime: 60_000 },\n stable: { staleTime: 300_000 },\n static: { staleTime: 600_000 },\n} as const;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"prefetch.d.ts","names":[],"sources":["../src/prefetch.ts"],"mappings":";;;UASiB,eAAA;EACf,SAAA;AAAA;AAAA,UAGe,cAAA;EAHf;;AAGF;;;;;EAQE,YAAA,GACE,WAAA,EAAa,WAAA,EACb,MAAA,GAAS,MAAA,mBACT,OAAA,GAAU,eAAA,KACP,OAAA;EAAA;;;;;;;EASL,cAAA,GACE,WAAA,EAAa,WAAA,EACb,EAAA,UACA,OAAA,GAAU,eAAA,KACP,OAAA;AAAA;;;;;;;;;;;;;;;AA4CP;;;;;;;;;;;iBAAgB,oBAAA,CACd,GAAA;EACE,MAAA,GAAS,IAAA;IACP,MAAA,GAAS,MAAA;IACT,KAAA;IACA,cAAA;EAAA,MACI,OAAA;EACN,OAAA,GAAU,IAAA;IACR,EAAA;IACA,KAAA;IACA,cAAA;EAAA,MACI,OAAA;AAAA,GAER,SAAA,WACC,cAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"prefetch.js","names":[],"sources":["../src/prefetch.ts"],"sourcesContent":["import { dehydrate, type QueryClient, type QueryKey } from '@tanstack/react-query';\n\n// Re-export for convenience in server components\nexport { dehydrate } from '@tanstack/react-query';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PrefetchOptions {\n staleTime?: number;\n}\n\nexport interface CrudPrefetcher {\n /**\n * Prefetch a list query on the server. Uses the same query keys as useList.\n *\n * @example\n * const queryClient = getQueryClient();\n * await productsPrefetcher.prefetchList(queryClient, { limit: 20 });\n */\n prefetchList: (\n queryClient: QueryClient,\n params?: Record<string, unknown>,\n options?: PrefetchOptions,\n ) => Promise<void>;\n\n /**\n * Prefetch a detail query on the server. Uses the same query keys as useDetail.\n *\n * @example\n * const queryClient = getQueryClient();\n * await productsPrefetcher.prefetchDetail(queryClient, productId);\n */\n prefetchDetail: (\n queryClient: QueryClient,\n id: string,\n options?: PrefetchOptions,\n ) => Promise<void>;\n}\n\n// ============================================================================\n// Query Key Generators (must match createQueryKeys in query.ts)\n// ============================================================================\n\nfunction scopedListKey(entityKey: string, scope: string, params?: Record<string, unknown>): QueryKey {\n return [entityKey, 'list', { _scope: scope, ...(params || {}) }];\n}\n\nfunction detailKey(entityKey: string, id: string): QueryKey {\n return [entityKey, 'detail', id];\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\n/**\n * Create server-safe prefetch helpers for CRUD queries.\n * Use in Next.js server components to pre-populate the query cache before rendering.\n *\n * @example\n * // products-prefetch.ts\n * import { productsApi } from '@/api/products-api';\n * import { createCrudPrefetcher } from '@classytic/arc-next/prefetch';\n * export const productsPrefetcher = createCrudPrefetcher(productsApi, 'products');\n *\n * // app/products/page.tsx (server component)\n * import { getQueryClient } from '@classytic/arc-next/query-client';\n * import { dehydrate } from '@classytic/arc-next/prefetch';\n * import { HydrationBoundary } from '@tanstack/react-query';\n *\n * export default async function ProductsPage() {\n * const queryClient = getQueryClient();\n * await productsPrefetcher.prefetchList(queryClient, { limit: 20 });\n * return (\n * <HydrationBoundary state={dehydrate(queryClient)}>\n * <ProductsList />\n * </HydrationBoundary>\n * );\n * }\n */\nexport function createCrudPrefetcher(\n api: {\n getAll: (opts: {\n params?: Record<string, unknown>;\n token?: string | null;\n organizationId?: string | null;\n }) => Promise<unknown>;\n getById: (opts: {\n id: string;\n token?: string | null;\n organizationId?: string | null;\n }) => Promise<unknown>;\n },\n entityKey: string,\n): CrudPrefetcher {\n return {\n async prefetchList(queryClient, params = {}, options = {}) {\n const { organizationId, ...restParams } = params;\n const scope = organizationId ? 'tenant' : 'super-admin';\n const queryKey = scopedListKey(entityKey, scope, { organizationId, ...restParams });\n\n await queryClient.prefetchQuery({\n queryKey,\n queryFn: () => api.getAll({\n params: restParams,\n organizationId: (organizationId as string | null) ?? null,\n }),\n staleTime: options.staleTime,\n });\n },\n\n async prefetchDetail(queryClient, id, options = {}) {\n const queryKey = detailKey(entityKey, id);\n\n await queryClient.prefetchQuery({\n queryKey,\n queryFn: () => api.getById({ id }),\n staleTime: options.staleTime,\n });\n },\n };\n}\n"],"mappings":";;;AA6CA,SAAS,cAAc,WAAmB,OAAe,QAA4C;AACnG,QAAO;EAAC;EAAW;EAAQ;GAAE,QAAQ;GAAO,GAAI,UAAU,EAAE;GAAG;EAAC;;AAGlE,SAAS,UAAU,WAAmB,IAAsB;AAC1D,QAAO;EAAC;EAAW;EAAU;EAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgClC,SAAgB,qBACd,KAYA,WACgB;AAChB,QAAO;EACL,MAAM,aAAa,aAAa,SAAS,EAAE,EAAE,UAAU,EAAE,EAAE;GACzD,MAAM,EAAE,gBAAgB,GAAG,eAAe;GAE1C,MAAM,WAAW,cAAc,WADjB,iBAAiB,WAAW,eACO;IAAE;IAAgB,GAAG;IAAY,CAAC;AAEnF,SAAM,YAAY,cAAc;IAC9B;IACA,eAAe,IAAI,OAAO;KACxB,QAAQ;KACR,gBAAiB,kBAAoC;KACtD,CAAC;IACF,WAAW,QAAQ;IACpB,CAAC;;EAGJ,MAAM,eAAe,aAAa,IAAI,UAAU,EAAE,EAAE;GAClD,MAAM,WAAW,UAAU,WAAW,GAAG;AAEzC,SAAM,YAAY,cAAc;IAC9B;IACA,eAAe,IAAI,QAAQ,EAAE,IAAI,CAAC;IAClC,WAAW,QAAQ;IACpB,CAAC;;EAEL"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"query-client.d.ts","names":[],"sources":["../src/query-client.ts"],"mappings":";;;UAUiB,oBAAA;EACf,SAAA;EACA,MAAA;EACA,KAAA;EACA,oBAAA;AAAA;;;;;;;AAoDF;;;;;;iBAAgB,cAAA,CAAe,SAAA,GAAY,oBAAA,GAAuB,WAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"query-client.js","names":[],"sources":["../src/query-client.ts"],"sourcesContent":["import {\n isServer,\n QueryClient,\n defaultShouldDehydrateQuery,\n} from '@tanstack/react-query';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface QueryClientOverrides {\n staleTime?: number;\n gcTime?: number;\n retry?: number | boolean;\n refetchOnWindowFocus?: boolean;\n}\n\n// ============================================================================\n// Defaults\n// ============================================================================\n\nconst DEFAULTS: Required<QueryClientOverrides> = {\n staleTime: 5 * 60 * 1000,\n gcTime: 30 * 60 * 1000,\n retry: 0,\n refetchOnWindowFocus: false,\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nfunction makeQueryClient(overrides?: QueryClientOverrides): QueryClient {\n const opts = { ...DEFAULTS, ...overrides };\n\n return new QueryClient({\n defaultOptions: {\n queries: {\n retry: opts.retry as number,\n staleTime: opts.staleTime,\n gcTime: opts.gcTime,\n refetchOnWindowFocus: opts.refetchOnWindowFocus,\n },\n dehydrate: {\n shouldDehydrateQuery: (query) =>\n defaultShouldDehydrateQuery(query) ||\n query.state.status === 'pending',\n },\n },\n });\n}\n\nlet browserQueryClient: QueryClient | undefined;\n\n/**\n * SSR-safe QueryClient singleton factory.\n * Server: always creates a new instance (one per request).\n * Browser: reuses a singleton (survives Suspense re-renders).\n *\n * @example\n * // In layout.tsx or providers\n * const queryClient = getQueryClient();\n *\n * // With overrides\n * const queryClient = getQueryClient({ staleTime: 60_000 });\n */\nexport function getQueryClient(overrides?: QueryClientOverrides): QueryClient {\n if (isServer) {\n return makeQueryClient(overrides);\n }\n\n if (!browserQueryClient) {\n browserQueryClient = makeQueryClient(overrides);\n }\n return browserQueryClient;\n}\n"],"mappings":";;;AAqBA,MAAM,WAA2C;CAC/C,WAAW,MAAS;CACpB,QAAQ,OAAU;CAClB,OAAO;CACP,sBAAsB;CACvB;AAMD,SAAS,gBAAgB,WAA+C;CACtE,MAAM,OAAO;EAAE,GAAG;EAAU,GAAG;EAAW;AAE1C,QAAO,IAAI,YAAY,EACrB,gBAAgB;EACd,SAAS;GACP,OAAO,KAAK;GACZ,WAAW,KAAK;GAChB,QAAQ,KAAK;GACb,sBAAsB,KAAK;GAC5B;EACD,WAAW,EACT,uBAAuB,UACrB,4BAA4B,MAAM,IAClC,MAAM,MAAM,WAAW,WAC1B;EACF,EACF,CAAC;;AAGJ,IAAI;;;;;;;;;;;;;AAcJ,SAAgB,eAAe,WAA+C;AAC5E,KAAI,SACF,QAAO,gBAAgB,UAAU;AAGnC,KAAI,CAAC,mBACH,sBAAqB,gBAAgB,UAAU;AAEjD,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"query.d.ts","names":[],"sources":["../src/query.ts"],"mappings":"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"}
package/dist/query.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"query.js","names":[],"sources":["../src/query.ts"],"sourcesContent":["\"use client\";\n\nimport { useQuery, useInfiniteQuery, useQueryClient, keepPreviousData, type QueryKey, type InfiniteData } from \"@tanstack/react-query\";\nimport { useEffect } from \"react\";\nimport type { QueryClient } from \"@tanstack/react-query\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PaginationData {\n total: number;\n pages: number;\n page: number;\n limit: number;\n hasNext: boolean;\n hasPrev: boolean;\n}\n\n/** Request-level options passed through to the fetch call */\nexport interface RequestPassthrough {\n cache?: RequestCache;\n revalidate?: number;\n tags?: string[];\n headerOptions?: Record<string, string>;\n signal?: AbortSignal;\n}\n\nexport interface ListQueryOptions<TData = unknown> {\n public?: boolean;\n enabled?: boolean;\n staleTime?: number;\n gcTime?: number;\n refetchOnWindowFocus?: boolean;\n structuralSharing?: boolean;\n prefillDetailCache?: boolean;\n refetchInterval?: number | false;\n refetchIntervalInBackground?: boolean;\n _scope?: string;\n /** Transform raw API response before returning. Runs on each render, receives raw data. */\n select?: (data: unknown) => TData;\n /** Pass-through options for the underlying fetch request (cache, revalidate, tags, headers) */\n request?: RequestPassthrough;\n}\n\nexport interface DetailQueryOptions<TData = unknown> {\n public?: boolean;\n organizationId?: string | null;\n enabled?: boolean;\n staleTime?: number;\n gcTime?: number;\n structuralSharing?: boolean;\n refetchInterval?: number | false;\n refetchIntervalInBackground?: boolean;\n /** Query params passed to getById (e.g. select, populate) */\n params?: { select?: string; populate?: string | string[] };\n /** Transform raw API response before returning. Runs on each render, receives raw data. */\n select?: (data: unknown) => TData;\n /** Pass-through options for the underlying fetch request (cache, revalidate, tags, headers) */\n request?: RequestPassthrough;\n}\n\nexport interface ListQueryResult<T> {\n items: T[];\n pagination: PaginationData | null;\n isLoading: boolean;\n isFetching: boolean;\n isError: boolean;\n isSuccess: boolean;\n isStale: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n data: unknown;\n}\n\nexport interface DetailQueryResult<T> {\n item: T | null;\n isLoading: boolean;\n isFetching: boolean;\n isError: boolean;\n isSuccess: boolean;\n isStale: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n data: unknown;\n}\n\nexport interface QueryKeys {\n all: string[];\n lists: () => QueryKey;\n list: (params?: unknown) => QueryKey;\n details: () => QueryKey;\n detail: (id: string) => QueryKey;\n custom: (key: string, ...args: unknown[]) => QueryKey;\n scopedList: (scope: string, params?: unknown) => QueryKey;\n}\n\nexport interface CacheUtils<T> {\n invalidateAll: (client: QueryClient) => Promise<void>;\n invalidateLists: (client: QueryClient) => Promise<void>;\n invalidateDetail: (client: QueryClient, id: string) => Promise<void>;\n setDetail: (client: QueryClient, id: string, data: T) => void;\n getDetail: (client: QueryClient, id: string) => T | undefined;\n removeDetail: (client: QueryClient, id: string) => void;\n}\n\n// ============================================================================\n// Default Config\n// ============================================================================\n\nexport const DEFAULT_QUERY_CONFIG = {\n staleTime: 5 * 60 * 1000,\n gcTime: 30 * 60 * 1000,\n refetchOnWindowFocus: false,\n retry: 0,\n} as const;\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\nexport function getItemId(item: unknown): string | null {\n if (!item || typeof item !== \"object\") return null;\n const obj = item as Record<string, unknown>;\n const id = obj._id ?? obj.id;\n return typeof id === \"string\" ? id : id ? String(id) : null;\n}\n\nfunction normalizePagination(data: unknown): PaginationData | null {\n if (!data || typeof data !== \"object\") return null;\n const d = data as Record<string, unknown>;\n\n const hasTotal = d.total != null || d.totalDocs != null;\n const hasPages = d.pages != null || d.totalPages != null;\n if (!hasTotal && !hasPages) return null;\n\n return {\n total: Number(d.total ?? d.totalDocs ?? 0),\n pages: Number(d.pages ?? d.totalPages ?? 1),\n page: Number(d.page ?? d.currentPage ?? 1),\n limit: Number(d.limit ?? 10),\n hasNext: Boolean(d.hasNext ?? d.hasNextPage ?? d.hasMore ?? false),\n hasPrev: Boolean(d.hasPrev ?? d.hasPrevPage ?? false),\n };\n}\n\nfunction extractItems<T>(data: unknown): T[] {\n if (!data) return [];\n if (Array.isArray(data)) return data as T[];\n if (typeof data !== \"object\") return [];\n\n const d = data as Record<string, unknown>;\n const items = d.docs ?? d.data ?? d.items ?? d.results;\n return Array.isArray(items) ? (items as T[]) : [];\n}\n\nfunction extractItem<T>(data: unknown): T | null {\n if (!data) return null;\n if (typeof data !== \"object\") return null;\n\n const d = data as Record<string, unknown>;\n return (d.data ?? d) as T | null;\n}\n\nexport function updateListCache<T>(listData: unknown, updater: (items: T[]) => T[]): unknown {\n if (!listData) return listData;\n\n if (Array.isArray(listData)) {\n return updater(listData as T[]);\n }\n\n if (typeof listData !== \"object\") return listData;\n const d = listData as Record<string, unknown>;\n\n // Detect the items array field: docs > data > items > results (same order as extractItems)\n const arrayField = \"docs\" in d ? \"docs\"\n : (Array.isArray(d.data) ? \"data\"\n : (\"items\" in d && Array.isArray(d.items) ? \"items\"\n : (\"results\" in d && Array.isArray(d.results) ? \"results\" : null)));\n\n if (!arrayField) return listData;\n\n const updated = updater(d[arrayField] as T[]);\n const original = d[arrayField] as T[];\n const delta = updated.length - original.length;\n\n // Update total/totalDocs when item count changes (optimistic add/delete)\n const result: Record<string, unknown> = { ...d, [arrayField]: updated };\n if (delta !== 0) {\n if (d.total != null) result.total = Math.max(0, Number(d.total) + delta);\n if (d.totalDocs != null) result.totalDocs = Math.max(0, Number(d.totalDocs) + delta);\n }\n\n return result;\n}\n\n// ============================================================================\n// Query Keys Factory\n// ============================================================================\n\nexport function createQueryKeys(entityKey: string): QueryKeys {\n return {\n all: [entityKey],\n lists: () => [entityKey, \"list\"],\n list: (params) => [entityKey, \"list\", params],\n details: () => [entityKey, \"detail\"],\n detail: (id) => [entityKey, \"detail\", id],\n custom: (key, ...args) => [entityKey, key, ...args],\n scopedList: (scope, params) => [entityKey, \"list\", { _scope: scope, ...(params as object) }],\n };\n}\n\n// ============================================================================\n// Cache Utilities Factory\n// ============================================================================\n\nexport function createCacheUtils<T>(KEYS: QueryKeys): CacheUtils<T> {\n return {\n invalidateAll: (client) => client.invalidateQueries({ queryKey: KEYS.all }),\n invalidateLists: (client) => client.invalidateQueries({ queryKey: KEYS.lists() }),\n invalidateDetail: (client, id) => client.invalidateQueries({ queryKey: KEYS.detail(id) }),\n setDetail: (client, id, data) => client.setQueryData(KEYS.detail(id), { data }),\n getDetail: (client, id) => {\n const cached = client.getQueryData(KEYS.detail(id)) as { data?: T } | undefined;\n return cached?.data;\n },\n removeDetail: (client, id) => client.removeQueries({ queryKey: KEYS.detail(id) }),\n };\n}\n\n// ============================================================================\n// List Query Hook\n// ============================================================================\n\nexport interface CreateListQueryConfig {\n queryKey: QueryKey;\n queryFn: (context: { signal?: AbortSignal }) => Promise<unknown>;\n enabled?: boolean;\n options?: Record<string, unknown>;\n prefillDetailCache?: boolean;\n detailKeyBuilder?: (id: string) => QueryKey;\n select?: (data: unknown) => unknown;\n}\n\nexport function createListQuery<T>({\n queryKey,\n queryFn,\n enabled = true,\n options = {},\n prefillDetailCache = true,\n detailKeyBuilder,\n select,\n}: CreateListQueryConfig): ListQueryResult<T> {\n const queryClient = useQueryClient();\n\n const query = useQuery({\n queryKey,\n queryFn: ({ signal }) => queryFn({ signal }),\n enabled,\n ...DEFAULT_QUERY_CONFIG,\n ...options,\n ...(select ? { select } : {}),\n placeholderData: keepPreviousData,\n });\n\n const items = extractItems<T>(query.data);\n const pagination = normalizePagination(query.data);\n\n useEffect(() => {\n if (!prefillDetailCache || !detailKeyBuilder || items.length === 0) return;\n\n items.forEach((item) => {\n const id = getItemId(item);\n if (id) queryClient.setQueryData(detailKeyBuilder(id), { data: item });\n });\n }, [items, prefillDetailCache, detailKeyBuilder, queryClient]);\n\n return {\n items,\n pagination,\n isLoading: query.isLoading,\n isFetching: query.isFetching,\n isError: query.isError,\n isSuccess: query.isSuccess,\n isStale: query.isStale,\n error: query.error,\n refetch: query.refetch,\n data: query.data,\n };\n}\n\n// ============================================================================\n// Detail Query Hook\n// ============================================================================\n\nexport interface CreateDetailQueryConfig {\n queryKey: QueryKey;\n queryFn: (context: { signal?: AbortSignal }) => Promise<unknown>;\n enabled?: boolean;\n options?: Record<string, unknown>;\n select?: (data: unknown) => unknown;\n}\n\nexport function createDetailQuery<T>({\n queryKey,\n queryFn,\n enabled = true,\n options = {},\n select,\n}: CreateDetailQueryConfig): DetailQueryResult<T> {\n const query = useQuery({\n queryKey,\n queryFn: ({ signal }) => queryFn({ signal }),\n enabled,\n ...DEFAULT_QUERY_CONFIG,\n ...options,\n ...(select ? { select } : {}),\n });\n\n const item = extractItem<T>(query.data);\n\n return {\n item,\n isLoading: query.isLoading,\n isFetching: query.isFetching,\n isError: query.isError,\n isSuccess: query.isSuccess,\n isStale: query.isStale,\n error: query.error,\n refetch: query.refetch,\n data: query.data,\n };\n}\n\n// ============================================================================\n// Infinite List Query Hook\n// ============================================================================\n\nexport interface InfiniteListQueryOptions {\n public?: boolean;\n enabled?: boolean;\n staleTime?: number;\n gcTime?: number;\n refetchOnWindowFocus?: boolean;\n structuralSharing?: boolean;\n _scope?: string;\n request?: RequestPassthrough;\n}\n\nexport interface InfiniteListQueryResult<T> {\n items: T[];\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n isFetchingNextPage: boolean;\n isFetchingPreviousPage: boolean;\n fetchNextPage: () => void;\n fetchPreviousPage: () => void;\n isLoading: boolean;\n isFetching: boolean;\n isError: boolean;\n isSuccess: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n data: InfiniteData<unknown> | undefined;\n}\n\nexport interface CreateInfiniteListQueryConfig {\n queryKey: QueryKey;\n queryFn: (context: { signal?: AbortSignal; pageParam: unknown }) => Promise<unknown>;\n enabled?: boolean;\n options?: Record<string, unknown>;\n initialPageParam?: unknown;\n getNextPageParam: (lastPage: unknown) => unknown;\n getPreviousPageParam?: (firstPage: unknown) => unknown;\n}\n\nexport function createInfiniteListQuery<T>({\n queryKey,\n queryFn,\n enabled = true,\n options = {},\n initialPageParam = 1,\n getNextPageParam,\n getPreviousPageParam,\n}: CreateInfiniteListQueryConfig): InfiniteListQueryResult<T> {\n const query = useInfiniteQuery({\n queryKey,\n queryFn: ({ pageParam, signal }) => queryFn({ pageParam, signal }),\n enabled,\n initialPageParam,\n getNextPageParam,\n getPreviousPageParam,\n ...DEFAULT_QUERY_CONFIG,\n ...options,\n });\n\n const items: T[] = query.data?.pages.flatMap((page) => extractItems<T>(page)) ?? [];\n\n return {\n items,\n hasNextPage: query.hasNextPage,\n hasPreviousPage: query.hasPreviousPage,\n isFetchingNextPage: query.isFetchingNextPage,\n isFetchingPreviousPage: query.isFetchingPreviousPage,\n fetchNextPage: query.fetchNextPage,\n fetchPreviousPage: query.fetchPreviousPage,\n isLoading: query.isLoading,\n isFetching: query.isFetching,\n isError: query.isError,\n isSuccess: query.isSuccess,\n error: query.error,\n refetch: query.refetch,\n data: query.data,\n };\n}\n"],"mappings":"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"}