@classytic/arc-next 0.2.0 → 0.2.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/api.d.ts CHANGED
@@ -77,6 +77,16 @@ interface RequestOptions {
77
77
  responseType?: 'json' | 'blob' | 'text';
78
78
  signal?: AbortSignal;
79
79
  }
80
+ /**
81
+ * Arc scope for multi-tenant APIs.
82
+ *
83
+ * - `'tenant'` (default) — Org-scoped. Hooks auto-inject `organizationId` from auth context.
84
+ * - `'platform'` — Platform admin scope. Skips org injection, sets `x-arc-scope: platform`
85
+ * header so Arc's elevation plugin grants cross-org access for superadmins.
86
+ */
87
+ type ArcScope = 'tenant' | 'platform';
88
+ /** Header name used by Arc's elevation plugin */
89
+ declare const ARC_SCOPE_HEADER = "x-arc-scope";
80
90
  interface BaseApiConfig {
81
91
  basePath?: string;
82
92
  defaultParams?: {
@@ -86,13 +96,32 @@ interface BaseApiConfig {
86
96
  };
87
97
  cache?: RequestCache;
88
98
  headers?: Record<string, string>;
99
+ /**
100
+ * API scope — controls org context injection and Arc scope headers.
101
+ *
102
+ * @default 'tenant'
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * // Org-scoped API (default) — auto-injects organizationId
107
+ * const postsApi = createCrudApi('posts', { basePath: '/api' });
108
+ *
109
+ * // Platform admin API — skips org injection, adds x-arc-scope header
110
+ * const adminApi = createCrudApi('subscriptions', {
111
+ * basePath: '/api',
112
+ * scope: 'platform',
113
+ * });
114
+ * ```
115
+ */
116
+ scope?: ArcScope;
89
117
  client?: ArcClient;
90
118
  }
91
119
  declare class BaseApi<TDoc = Record<string, unknown>, TCreate = Partial<TDoc>, TUpdate = Partial<TDoc>> {
92
120
  readonly entity: string;
93
- readonly config: Required<Omit<BaseApiConfig, 'client'>>;
121
+ readonly config: Required<Omit<BaseApiConfig, 'client' | 'scope'>>;
94
122
  readonly baseUrl: string;
95
123
  private readonly requestFn;
124
+ readonly scope: ArcScope;
96
125
  constructor(entity: string, config?: BaseApiConfig);
97
126
  /** Merge per-instance headers into request options */
98
127
  private withHeaders;
@@ -225,5 +254,5 @@ declare function isOffsetPagination<T>(response: PaginatedResponse<T>): response
225
254
  declare function isKeysetPagination<T>(response: PaginatedResponse<T>): response is KeysetPaginationResponse<T>;
226
255
  declare function isAggregatePagination<T>(response: PaginatedResponse<T>): response is AggregatePaginationResponse<T>;
227
256
  //#endregion
228
- export { AggregatePaginationResponse, ApiResponse, BaseApi, BaseApiConfig, DeleteResponse, ExtractDoc, FilterOperator, KeysetPaginationResponse, OffsetPaginationResponse, PaginatedResponse, PopulateOption, QueryParams, RequestOptions, SortDirection, SortSpec, createCrudApi, isAggregatePagination, isKeysetPagination, isOffsetPagination };
257
+ export { ARC_SCOPE_HEADER, AggregatePaginationResponse, ApiResponse, ArcScope, BaseApi, BaseApiConfig, DeleteResponse, ExtractDoc, FilterOperator, KeysetPaginationResponse, OffsetPaginationResponse, PaginatedResponse, PopulateOption, QueryParams, RequestOptions, SortDirection, SortSpec, createCrudApi, isAggregatePagination, isKeysetPagination, isOffsetPagination };
229
258
  //# sourceMappingURL=api.d.ts.map
package/dist/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","names":[],"sources":["../src/api.ts"],"mappings":"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"}
1
+ {"version":3,"file":"api.d.ts","names":[],"sources":["../src/api.ts"],"mappings":"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"}
package/dist/api.js CHANGED
@@ -1,14 +1,19 @@
1
1
  import { createQueryString, handleApiRequest } from "./client.js";
2
2
 
3
3
  //#region src/api.ts
4
+ /** Header name used by Arc's elevation plugin */
5
+ const ARC_SCOPE_HEADER = "x-arc-scope";
4
6
  var BaseApi = class {
5
7
  entity;
6
8
  config;
7
9
  baseUrl;
8
10
  requestFn;
11
+ scope;
9
12
  constructor(entity, config = {}) {
10
13
  this.entity = entity;
14
+ this.scope = config.scope ?? "tenant";
11
15
  this.requestFn = config.client?.request ?? handleApiRequest;
16
+ const scopeHeaders = this.scope === "platform" ? { [ARC_SCOPE_HEADER]: "platform" } : {};
12
17
  this.config = {
13
18
  basePath: config.basePath ?? "/api/v1",
14
19
  defaultParams: {
@@ -17,7 +22,10 @@ var BaseApi = class {
17
22
  ...config.defaultParams || {}
18
23
  },
19
24
  cache: config.cache ?? "no-store",
20
- headers: { ...config.headers || {} }
25
+ headers: {
26
+ ...scopeHeaders,
27
+ ...config.headers || {}
28
+ }
21
29
  };
22
30
  this.baseUrl = `${this.config.basePath}/${this.entity}`;
23
31
  }
@@ -176,5 +184,5 @@ function isAggregatePagination(response) {
176
184
  }
177
185
 
178
186
  //#endregion
179
- export { BaseApi, createCrudApi, isAggregatePagination, isKeysetPagination, isOffsetPagination };
187
+ export { ARC_SCOPE_HEADER, BaseApi, createCrudApi, isAggregatePagination, isKeysetPagination, isOffsetPagination };
180
188
  //# sourceMappingURL=api.js.map
package/dist/api.js.map CHANGED
@@ -1 +1 @@
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
+ {"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\n/**\n * Arc scope for multi-tenant APIs.\n *\n * - `'tenant'` (default) — Org-scoped. Hooks auto-inject `organizationId` from auth context.\n * - `'platform'` — Platform admin scope. Skips org injection, sets `x-arc-scope: platform`\n * header so Arc's elevation plugin grants cross-org access for superadmins.\n */\nexport type ArcScope = 'tenant' | 'platform';\n\n/** Header name used by Arc's elevation plugin */\nexport const ARC_SCOPE_HEADER = 'x-arc-scope';\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 /**\n * API scope — controls org context injection and Arc scope headers.\n *\n * @default 'tenant'\n *\n * @example\n * ```ts\n * // Org-scoped API (default) — auto-injects organizationId\n * const postsApi = createCrudApi('posts', { basePath: '/api' });\n *\n * // Platform admin API — skips org injection, adds x-arc-scope header\n * const adminApi = createCrudApi('subscriptions', {\n * basePath: '/api',\n * scope: 'platform',\n * });\n * ```\n */\n scope?: ArcScope;\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' | 'scope'>>;\n readonly baseUrl: string;\n private readonly requestFn: RequestFn;\n\n readonly scope: ArcScope;\n\n constructor(entity: string, config: BaseApiConfig = {}) {\n this.entity = entity;\n this.scope = config.scope ?? 'tenant';\n this.requestFn = config.client?.request ?? handleApiRequest;\n\n // Build headers: merge user headers + scope header\n const scopeHeaders: Record<string, string> =\n this.scope === 'platform' ? { [ARC_SCOPE_HEADER]: 'platform' } : {};\n\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 ...scopeHeaders,\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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"}
package/dist/hooks.d.ts CHANGED
@@ -5,6 +5,8 @@ import { QueryKey } from "@tanstack/react-query";
5
5
 
6
6
  //#region src/hooks.d.ts
7
7
  interface CrudApi<T, TCreate = Partial<T>, TUpdate = Partial<T>> {
8
+ /** Scope from BaseApi — used to auto-detect platformScoped */
9
+ scope?: 'tenant' | 'platform';
8
10
  getAll: (options: {
9
11
  token?: string | null;
10
12
  organizationId?: string | null;
@@ -65,6 +67,18 @@ interface CrudHooksConfig<T, TCreate = Partial<T>, TUpdate = Partial<T>> {
65
67
  entityKey: string;
66
68
  singular: string;
67
69
  plural?: string;
70
+ /**
71
+ * Platform-scoped hooks skip automatic organizationId injection.
72
+ *
73
+ * Use this for admin/superadmin hooks that query across all orgs
74
+ * (e.g., APIs configured with `x-arc-scope: platform`).
75
+ *
76
+ * When true, the hooks will NOT auto-inject the user's active
77
+ * organizationId into requests — the API's own headers control scoping.
78
+ *
79
+ * @default false
80
+ */
81
+ platformScoped?: boolean;
68
82
  defaults?: {
69
83
  staleTime?: number;
70
84
  gcTime?: number;
@@ -176,6 +190,7 @@ declare function createCrudHooks<T, TCreate = Partial<T>, TUpdate = Partial<T>>(
176
190
  api,
177
191
  entityKey,
178
192
  singular,
193
+ platformScoped,
179
194
  defaults,
180
195
  callbacks,
181
196
  client
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":"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"}
1
+ {"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":"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"}
package/dist/hooks.js CHANGED
@@ -23,7 +23,8 @@ function createEnabledRule(token, options) {
23
23
  if (getAuthMode() === "cookie" || options.public) return options.enabled ?? true;
24
24
  return options.enabled !== void 0 ? options.enabled && !!token : !!token;
25
25
  }
26
- function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks = {}, client }) {
26
+ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults = {}, callbacks = {}, client }) {
27
+ const isPlatform = platformScoped ?? api.scope === "platform";
27
28
  const KEYS = createQueryKeys(entityKey);
28
29
  const cache = createCacheUtils(KEYS);
29
30
  const instanceToast = client?.toast;
@@ -55,13 +56,13 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
55
56
  token = auth.token;
56
57
  params = tokenOrParams ?? {};
57
58
  options = paramsOrOptions ?? {};
58
- if (auth.organizationId && !params.organizationId) params = {
59
+ if (!isPlatform && auth.organizationId && !params.organizationId) params = {
59
60
  ...params,
60
61
  organizationId: auth.organizationId
61
62
  };
62
63
  }
63
64
  const { organizationId, ...restParams } = params;
64
- const scope = options._scope || (organizationId ? "tenant" : "super-admin");
65
+ const scope = options._scope || (isPlatform ? "platform" : organizationId ? "tenant" : "super-admin");
65
66
  const { request: requestOpts, ...queryOpts } = options;
66
67
  return createListQuery({
67
68
  queryKey: KEYS.scopedList(scope, {
@@ -101,7 +102,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
101
102
  const auth = getAuthContext();
102
103
  token = auth.token;
103
104
  options = tokenOrOptions ?? {};
104
- if (auth.organizationId && !options.organizationId) options = {
105
+ if (!isPlatform && auth.organizationId && !options.organizationId) options = {
105
106
  ...options,
106
107
  organizationId: auth.organizationId
107
108
  };
@@ -248,7 +249,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
248
249
  return {
249
250
  ...params,
250
251
  token: params.token ?? auth.token,
251
- organizationId: params.organizationId ?? auth.organizationId
252
+ organizationId: isPlatform ? params.organizationId ?? null : params.organizationId ?? auth.organizationId
252
253
  };
253
254
  };
254
255
  const create = async (params, options) => {
@@ -319,7 +320,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
319
320
  token = auth.token;
320
321
  params = tokenOrParams ?? {};
321
322
  options = paramsOrOptions ?? {};
322
- if (auth.organizationId && !params.organizationId) params = {
323
+ if (!isPlatform && auth.organizationId && !params.organizationId) params = {
323
324
  ...params,
324
325
  organizationId: auth.organizationId
325
326
  };
@@ -372,7 +373,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
372
373
  const auth = getAuthContext();
373
374
  return uploadApi({
374
375
  token: auth.token,
375
- organizationId: auth.organizationId,
376
+ organizationId: isPlatform ? null : auth.organizationId,
376
377
  data,
377
378
  id,
378
379
  path
@@ -394,7 +395,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
394
395
  const searchApi = api.search;
395
396
  const auth = getAuthContext();
396
397
  const token = auth.token;
397
- const organizationId = params?.organizationId ?? auth.organizationId;
398
+ const organizationId = platformScoped ? null : params?.organizationId ?? auth.organizationId;
398
399
  const { organizationId: _, ...restParams } = params ?? {};
399
400
  const searchParams = {
400
401
  q: query,
package/dist/hooks.js.map CHANGED
@@ -1 +1 @@
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":";;;;;;;;;;AA6MA,IAAI,gBAAsC;;;;;;;;AAS1C,SAAgB,oBAAoB,MAA2B;AAC7D,iBAAgB;;AAOlB,SAAS,kBAAkB,OAAsB,SAA2D;AAE1G,KAAI,aAAa,KAAK,YAAY,QAAQ,OACxC,QAAO,QAAQ,WAAW;AAG5B,QAAO,QAAQ,YAAY,SAAY,QAAQ,WAAW,CAAC,CAAC,QAAQ,CAAC,CAAC;;AAOxE,SAAgB,gBAA+D,EAC7E,KACA,WACA,UACA,WAAW,EAAE,EACb,YAAY,EAAE,EACd,UAC6E;CAC7E,MAAM,OAAO,gBAAgB,UAAU;CACvC,MAAM,QAAQ,iBAAoB,KAAK;CAGvC,MAAM,gBAA0C,QAAQ;CAExD,MAAM,qBAA2C,QAAQ,cAAc;CAEvE,MAAM,SAAS;EACb,GAAG;EACH,GAAG;EACH,mBAAmB,SAAS;EAC5B,UAAU;GACR,eAAe,GAAG,SAAS;GAC3B,aAAa,oBAAoB,SAAS,aAAa;GACvD,eAAe,GAAG,SAAS;GAC3B,aAAa,oBAAoB,SAAS,aAAa;GACvD,eAAe,GAAG,SAAS;GAC3B,aAAa,oBAAoB,SAAS,aAAa;GACvD,GAAG,SAAS;GACb;EACF;CAID,SAAS,QACP,eACA,iBACA,cACoB;EACpB,IAAI;EACJ,IAAI;EACJ,IAAI;AAGJ,MAAI,kBAAkB,QAAQ,OAAO,kBAAkB,UAAU;AAC/D,WAAQ;AACR,YAAU,mBAA+C,EAAE;AAC3D,aAAU,gBAAgB,EAAE;SACvB;GACL,MAAM,OAAO,gBAAgB;AAC7B,WAAQ,KAAK;AACb,YAAU,iBAA6C,EAAE;AACzD,aAAW,mBAAwC,EAAE;AACrD,OAAI,KAAK,kBAAkB,CAAC,OAAO,eACjC,UAAS;IAAE,GAAG;IAAQ,gBAAgB,KAAK;IAAgB;;EAI/D,MAAM,EAAE,gBAAgB,GAAG,eAAe;EAC1C,MAAM,QAAQ,QAAQ,WAAW,iBAAiB,WAAW;EAC7D,MAAM,EAAE,SAAS,aAAa,GAAG,cAAc;AAE/C,SAAO,gBAAmB;GACxB,UAAU,KAAK,WAAW,OAAO;IAAE;IAAgB,GAAG;IAAY,CAAC;GACnE,UAAU,EAAE,aAAa,IAAI,OAAO;IAAE;IAAuB;IAAiC,QAAQ;IAAY,SAAS;KAAE;KAAQ,GAAG;KAAa;IAAE,CAAC;GACxJ,SAAS,kBAAkB,OAAO,UAAU;GAC5C,SAAS;IACP,WAAW,UAAU,aAAa,OAAO;IACzC,QAAQ,UAAU,UAAU,OAAO;IACnC,sBAAsB,UAAU,wBAAwB,OAAO;IAC/D,mBAAmB,UAAU,qBAAqB,OAAO;IACzD,iBAAiB,UAAU;IAC3B,6BAA6B,UAAU;IACxC;GACD,oBAAoB,UAAU,sBAAsB;GACpD,mBAAmB,OAAO,KAAK,OAAO,GAAG;GACzC,QAAQ,UAAU;GACnB,CAAC;;CAKJ,SAAS,UACP,IACA,gBACA,cACsB;EACtB,IAAI;EACJ,IAAI;AAGJ,MAAI,mBAAmB,QAAQ,OAAO,mBAAmB,UAAU;AACjE,WAAQ;AACR,aAAU,gBAAgB,EAAE;SACvB;GACL,MAAM,OAAO,gBAAgB;AAC7B,WAAQ,KAAK;AACb,aAAW,kBAAyC,EAAE;AACtD,OAAI,KAAK,kBAAkB,CAAC,QAAQ,eAClC,WAAU;IAAE,GAAG;IAAS,gBAAgB,KAAK;IAAgB;;EAIjE,MAAM,EAAE,gBAAgB,QAAQ,aAAa,SAAS,aAAa,GAAG,gBAAgB;AAEtF,SAAO,kBAAqB;GAC1B,UAAU,cAAc,CAAC,GAAG,KAAK,OAAO,MAAM,GAAG,EAAE,YAAY,GAAG,KAAK,OAAO,MAAM,GAAG;GACvF,UAAU,EAAE,aAAa,IAAI,QAAQ;IAAM;IAAK;IAAO;IAAgB,QAAQ;IAAa,SAAS;KAAE;KAAQ,GAAG;KAAa;IAAE,CAAC;GAClI,SAAS,CAAC,CAAC,MAAM,kBAAkB,OAAO,YAAY;GACtD,SAAS;IACP,WAAW,YAAY,aAAa,OAAO;IAC3C,QAAQ,YAAY,UAAU,OAAO;IACrC,mBAAmB,YAAY,qBAAqB,OAAO;IAC3D,iBAAiB,YAAY;IAC7B,6BAA6B,YAAY;IAC1C;GACD,QAAQ,YAAY;GACrB,CAAC;;CAKJ,SAAS,aAA+C;EACtD,MAAM,cAAc,gBAAgB;EACpC,MAAM,YAAY,OAAO,MAAM;EAC/B,MAAM,cAAc,kBAAkB,CAAC,UAAU,SAAS,EAAE,CAAC;EAE7D,MAAM,iBAAiB,yBAAyB;GAC9C,aAAa,EAAE,OAAO,gBAAgB,WACpC,IAAI,OAAO;IAAE;IAAO;IAAgB;IAAM,CAAC;GAC7C;GACA,WAAW,CAAC,KAAK,OAAO,CAAC;GACzB;GACA,mBAAmB,SAAS,EAAE,WAAW;IACvC,MAAM,iBAAiB;KACrB,GAAI;KACJ,aAAa;MACZ,UAAU,KAAK,GAAG,OAAO,QAAQ,UAAU,KAAK,IAAI,QAAQ,KAAK,KAAK;KACxE;AACD,WAAO,gBAAgB,UAAU,QAAmB,CAAC,gBAAgB,GAAI,OAAO,EAAE,CAAE,CAAC;;GAEvF,YAAY,MAAM,cAAc;AAC9B,cAAU,UAAU,YAAY,MAAW,EAAE,MAAM,UAAU,MAAM,EAAE,OAAU;;GAEjF,UAAU,OAAO,cAAc;AAC7B,cAAU,UAAU,UAAU,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,OAAU;;GAE3E,YAAY,MAAM,OAAO,cAAc;AACrC,cAAU,UAAU,YAAY,MAAuB,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,OAAU;;GAEpG,UAAU;IAAE,SAAS,OAAO,SAAS;IAAe,OAAO,OAAO,SAAS;IAAa;GACxF,cAAc;GACf,CAAC;EAEF,MAAM,iBAAiB,yBAAyB;GAC9C,aAAa,EAAE,OAAO,gBAAgB,IAAI,WACxC,IAAI,OAAO;IAAE;IAAO;IAAgB;IAAI;IAAM,CAAC;GACjD;GACA,WAAW,CAAC,KAAK,OAAO,CAAC;GACzB;GACA,mBAAmB,SAAS,EAAE,IAAI,WAAW;IAC3C,MAAM,UAAU,gBAAgB,UAAU,SACvC,OAAO,EAAE,EAAE,KAAK,SAAU,UAAU,KAAK,KAAK,KAAK;KAAE,GAAI;KAAiB,GAAI;KAAiB,GAAG,KAAM,CAC1G;AACD,gBAAY,aAAa,KAAK,OAAO,GAAG,GAAG,YACzC,UAAU;KAAE,GAAI;KAAoB,MAAM;MAAE,GAAK,QAA8B,QAAQ,EAAE;MAAG,GAAI;MAAiB;KAAE,GAAG,QACvH;AACD,WAAO;;GAET,YAAY,MAAM,EAAE,IAAI,MAAM,iBAAiB;AAC7C,gBAAY,kBAAkB,EAAE,UAAU,KAAK,OAAO,GAAG,EAAE,CAAC;AAC5D,cAAU,UAAU,YAAY,MAAW;KAAE;KAAI,MAAM;KAAY,EAAE,OAAU;;GAEjF,UAAU,OAAO,EAAE,IAAI,WAAW;AAChC,cAAU,UAAU,UAAU,OAAO;KAAE;KAAI;KAAM,EAAE,OAAU;;GAE/D,YAAY,MAAM,OAAO,EAAE,IAAI,MAAM,iBAAiB;AACpD,cAAU,UAAU,YAAY,MAAuB,OAAO;KAAE;KAAI,MAAM;KAAY,EAAE,OAAU;;GAEpG,UAAU;IAAE,SAAS,OAAO,SAAS;IAAe,OAAO,OAAO,SAAS;IAAa;GACxF,cAAc;GACf,CAAC;EAEF,MAAM,iBAAiB,yBAAyB;GAC9C,aAAa,EAAE,OAAO,gBAAgB,SAAuB,IAAI,OAAO;IAAE;IAAO;IAAgB;IAAI,CAAC;GACtG;GACA,WAAW,CAAC,KAAK,OAAO,CAAC;GACzB;GACA,mBAAmB,SAAS,EAAE,SAAS;AACrC,gBAAY,cAAc,EAAE,UAAU,KAAK,OAAO,GAAG,EAAE,CAAC;AACxD,WAAO,gBAAgB,UAAU,SAAoB,OAAO,EAAE,EAAE,QAAQ,SAAS,UAAU,KAAK,KAAK,GAAG,CAAC;;GAE3G,YAAY,MAAM,EAAE,SAAS;AAC3B,cAAU,UAAU,YAAY,MAAM,EAAE,IAAI,EAAE,OAAU;;GAE1D,UAAU,OAAO,EAAE,SAAS;AAC1B,cAAU,UAAU,UAAU,OAAO,EAAE,IAAI,EAAE,OAAU;;GAEzD,YAAY,MAAM,OAAO,EAAE,SAAS;AAClC,cAAU,UAAU,YAAY,MAAM,OAAO,EAAE,IAAI,EAAE,OAAU;;GAEjE,UAAU;IAAE,SAAS,OAAO,SAAS;IAAe,OAAO,OAAO,SAAS;IAAa;GACxF,cAAc;GACf,CAAC;EAEF,MAAM,eAAoF,WAAiB;GACzG,MAAM,OAAO,gBAAgB;AAC7B,UAAO;IACL,GAAG;IACH,OAAO,OAAO,SAAS,KAAK;IAC5B,gBAAgB,OAAO,kBAAkB,KAAK;IAC/C;;EAGH,MAAM,SAAS,OAAO,QAAiC,YAAyC;AAC9F,aAAU,UAAU,SAAS,UAAU;AACvC,OAAI;IACF,MAAM,SAAS,MAAM,eAAe,YAAY,YAAY,OAAO,CAAC;AACpE,aAAS,YAAY,OAAY;AACjC,aAAS,YAAY,QAAa,KAAK;AACvC,WAAO;YACA,OAAO;AACd,aAAS,UAAU,MAAe;AAClC,aAAS,YAAY,QAAW,MAAe;AAC/C,UAAM;aACE;AACR,cAAU,UAAU;;;EAIxB,MAAM,SAAS,OAAO,QAA+B,YAAyC;AAC5F,aAAU,UAAU,SAAS,UAAU;AACvC,OAAI;IACF,MAAM,SAAS,MAAM,eAAe,YAAY,YAAY,OAAO,CAAC;AACpE,aAAS,YAAY,OAAY;AACjC,aAAS,YAAY,QAAa,KAAK;AACvC,WAAO;YACA,OAAO;AACd,aAAS,UAAU,MAAe;AAClC,aAAS,YAAY,QAAW,MAAe;AAC/C,UAAM;aACE;AACR,cAAU,UAAU;;;EAIxB,MAAM,SAAS,OAAO,QAAsB,YAA4C;AACtF,aAAU,UAAU,SAAS,UAAU;AACvC,OAAI;IACF,MAAM,SAAS,MAAM,eAAe,YAAY,YAAY,OAAO,CAAC;AACpE,aAAS,YAAY,OAAO;AAC5B,aAAS,YAAY,QAAQ,KAAK;AAClC,WAAO;YACA,OAAO;AACd,aAAS,UAAU,MAAe;AAClC,aAAS,YAAY,QAAW,MAAe;AAC/C,UAAM;aACE;AACR,cAAU,UAAU;;;AAIxB,SAAO;GACL;GACA;GACA;GACA,YAAY,eAAe;GAC3B,YAAY,eAAe;GAC3B,YAAY,eAAe;GAC3B,YAAY,eAAe,aAAa,eAAe,aAAa,eAAe;GACpF;;CAKH,SAAS,gBACP,eACA,iBACA,cAC4B;EAC5B,IAAI;EACJ,IAAI;EACJ,IAAI;AAEJ,MAAI,kBAAkB,QAAQ,OAAO,kBAAkB,UAAU;AAC/D,WAAQ;AACR,YAAU,mBAA+C,EAAE;AAC3D,aAAU,gBAAgB,EAAE;SACvB;GACL,MAAM,OAAO,gBAAgB;AAC7B,WAAQ,KAAK;AACb,YAAU,iBAA6C,EAAE;AACzD,aAAW,mBAAgD,EAAE;AAC7D,OAAI,KAAK,kBAAkB,CAAC,OAAO,eACjC,UAAS;IAAE,GAAG;IAAQ,gBAAgB,KAAK;IAAgB;;EAI/D,MAAM,EAAE,gBAAgB,GAAG,eAAe;EAC1C,MAAM,QAAQ,QAAQ,WAAW,iBAAiB,WAAW;EAC7D,MAAM,EAAE,SAAS,aAAa,GAAG,cAAc;AAE/C,SAAO,wBAA2B;GAChC,UAAU,CAAC,GAAG,KAAK,WAAW,OAAO;IAAE;IAAgB,GAAG;IAAY,CAAC,EAAE,WAAW;GACpF,UAAU,EAAE,WAAW,aAAa;IAClC,MAAM,mBAAmB,OAAO,cAAc,WAC1C,EAAE,OAAO,WAAW,GACpB,EAAE,MAAM,WAAW;AAEvB,WAAO,IAAI,OAAO;KAChB;KACgB;KAChB,QAAQ;MAAE,GAAG;MAAY,GAAG;MAAkB;KAC9C,SAAS;MAAE;MAAQ,GAAG;MAAa;KACpC,CAAC;;GAEJ,SAAS,kBAAkB,OAAO,UAAU;GAC5C,kBAAkB,WAAW,QAAQ,WAAW,QAAQ;GACxD,mBAAmB,aAAa;IAC9B,MAAM,OAAO;AACb,QAAI,mBAAmB,KAAK,CAC1B,QAAO,KAAK,UAAU,KAAK,OAAO;AAEpC,QAAI,mBAAmB,KAAK,CAC1B,QAAO,KAAK,UAAU,KAAK,OAAO,IAAI;IAGxC,MAAM,IAAI;AACV,QAAI,OAAO,EAAE,YAAY,aAAa,OAAO,EAAE,SAAS,SACtD,QAAO,EAAE,UAAW,EAAE,OAAkB,IAAI;;GAIhD,SAAS;IACP,WAAW,UAAU,aAAa,OAAO;IACzC,QAAQ,UAAU,UAAU,OAAO;IACnC,sBAAsB,UAAU,wBAAwB,OAAO;IAC/D,mBAAmB,UAAU,qBAAqB,OAAO;IAC1D;GACF,CAAC;;CAKJ,SAAS,UAAU,SAMhB;AACD,MAAI,CAAC,IAAI,OACP,OAAM,IAAI,MAAM,eAAe,UAAU,wCAAwC;EAGnF,MAAM,YAAY,IAAI;AAEtB,SAAO,0BAAmF;GACxF,aAAa,EAAE,MAAM,IAAI,WAAW;IAClC,MAAM,OAAO,gBAAgB;AAC7B,WAAO,UAAU;KAAE,OAAO,KAAK;KAAO,gBAAgB,KAAK;KAAgB;KAAM;KAAI;KAAM,CAAC;;GAE9F,mBAAmB,SAAS,qBAAqB,CAAC,KAAK,OAAO,CAAC;GAC/D,YAAY,SAAS,SAAS,YAAY,KAAK;GAC/C,UAAU,UAAU,SAAS,UAAU,MAAM;GAC7C,YAAY,MAAM,UAAU,SAAS,YAAY,MAAM,MAAM;GAC7D,UAAU,SAAS,YAAY;IAC7B,SAAS,GAAG,SAAS;IACrB,OAAO,oBAAoB,SAAS,aAAa;IAClD;GACD,cAAc;GACf,CAAC;;CAKJ,SAAS,UACP,OACA,QACA,SACoB;AACpB,MAAI,CAAC,IAAI,OACP,OAAM,IAAI,MAAM,eAAe,UAAU,uCAAuC;EAGlF,MAAM,YAAY,IAAI;EACtB,MAAM,OAAO,gBAAgB;EAC7B,MAAM,QAAQ,KAAK;EACnB,MAAM,iBAAiB,QAAQ,kBAAmC,KAAK;EACvE,MAAM,EAAE,gBAAgB,GAAG,GAAG,eAAe,UAAU,EAAE;EACzD,MAAM,eAAe;GAAE,GAAG;GAAO,GAAG;GAAY;EAChD,MAAM,EAAE,SAAS,aAAa,GAAG,cAAc,WAAW,EAAE;EAG5D,MAAM,kBAAkB,iBACpB;GAAE;GAAgB,GAAG;GAAc,GACnC;AAEJ,SAAO,gBAAmB;GACxB,UAAU;IAAC,GAAG,KAAK,OAAO;IAAE;IAAU;IAAgB;GACtD,UAAU,EAAE,aAAa,UAAU;IACjC;IACA;IACA,QAAQ;IACR,SAAS;KAAE;KAAQ,GAAG;KAAa;IACpC,CAAC;GACF,SAAS,MAAM,SAAS,KAAK,kBAAkB,OAAO,UAAU;GAChE,SAAS;IACP,WAAW,UAAU,aAAa,OAAO;IACzC,QAAQ,UAAU,UAAU,OAAO;IACpC;GACD,QAAQ,UAAU;GACnB,CAAC;;CAKJ,SAAS,kBAAyD,gBAO/D;AACD,SAAO,0BAA6C;GAClD,YAAY,eAAe;GAC3B,mBAAmB,eAAe,qBAAqB,CAAC,KAAK,OAAO,CAAC;GACrE,WAAW,eAAe;GAC1B,SAAS,eAAe;GACxB,WAAW,eAAe;GAC1B,UAAU,eAAe;GACzB,cAAc;GACf,CAAC;;CAKJ,SAAS,gBAA+B;EACtC,MAAM,cAAc,gBAAgB;EAEpC,MAAM,UADmB,sBAAsB,kBACZ;AAEnC,SAAO,aACJ,MAAc,MAAS,UAA6B,EAAE,KAAK;GAC1D,MAAM,KAAK,UAAU,KAAK;AAC1B,OAAI,GACF,aAAY,aAAa,KAAK,OAAO,GAAG,EAAE,EAAE,MAAM,MAAM,CAAC;AAG3D,OAAI,CAAC,OAAQ;GAEb,MAAM,EAAE,SAAS,MAAM,UAAU,UAAU;AAC3C,OAAI,QACF,QAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC;OAEhC,QAAO,KAAK,MAAM,EAAE,QAAQ,CAAC;KAGjC,CAAC,aAAa,OAAO,CACtB;;AAGH,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
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 /** Scope from BaseApi — used to auto-detect platformScoped */\n scope?: 'tenant' | 'platform';\n\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 /**\n * Platform-scoped hooks skip automatic organizationId injection.\n *\n * Use this for admin/superadmin hooks that query across all orgs\n * (e.g., APIs configured with `x-arc-scope: platform`).\n *\n * When true, the hooks will NOT auto-inject the user's active\n * organizationId into requests — the API's own headers control scoping.\n *\n * @default false\n */\n platformScoped?: boolean;\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 platformScoped,\n defaults = {},\n callbacks = {},\n client,\n}: CrudHooksConfig<T, TCreate, TUpdate>): CrudHooksReturn<T, TCreate, TUpdate> {\n // Auto-detect from api.scope when platformScoped is not explicitly set\n const isPlatform = platformScoped ?? (api.scope === 'platform');\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 (!isPlatform && auth.organizationId && !params.organizationId) {\n params = { ...params, organizationId: auth.organizationId };\n }\n }\n\n const { organizationId, ...restParams } = params;\n const scope = options._scope || (isPlatform ? \"platform\" : 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 (!isPlatform && 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: isPlatform ? (params.organizationId ?? null) : (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 (!isPlatform && 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: isPlatform ? null : 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 = platformScoped ? null : (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":";;;;;;;;;;AA4NA,IAAI,gBAAsC;;;;;;;;AAS1C,SAAgB,oBAAoB,MAA2B;AAC7D,iBAAgB;;AAOlB,SAAS,kBAAkB,OAAsB,SAA2D;AAE1G,KAAI,aAAa,KAAK,YAAY,QAAQ,OACxC,QAAO,QAAQ,WAAW;AAG5B,QAAO,QAAQ,YAAY,SAAY,QAAQ,WAAW,CAAC,CAAC,QAAQ,CAAC,CAAC;;AAOxE,SAAgB,gBAA+D,EAC7E,KACA,WACA,UACA,gBACA,WAAW,EAAE,EACb,YAAY,EAAE,EACd,UAC6E;CAE7E,MAAM,aAAa,kBAAmB,IAAI,UAAU;CACpD,MAAM,OAAO,gBAAgB,UAAU;CACvC,MAAM,QAAQ,iBAAoB,KAAK;CAGvC,MAAM,gBAA0C,QAAQ;CAExD,MAAM,qBAA2C,QAAQ,cAAc;CAEvE,MAAM,SAAS;EACb,GAAG;EACH,GAAG;EACH,mBAAmB,SAAS;EAC5B,UAAU;GACR,eAAe,GAAG,SAAS;GAC3B,aAAa,oBAAoB,SAAS,aAAa;GACvD,eAAe,GAAG,SAAS;GAC3B,aAAa,oBAAoB,SAAS,aAAa;GACvD,eAAe,GAAG,SAAS;GAC3B,aAAa,oBAAoB,SAAS,aAAa;GACvD,GAAG,SAAS;GACb;EACF;CAID,SAAS,QACP,eACA,iBACA,cACoB;EACpB,IAAI;EACJ,IAAI;EACJ,IAAI;AAGJ,MAAI,kBAAkB,QAAQ,OAAO,kBAAkB,UAAU;AAC/D,WAAQ;AACR,YAAU,mBAA+C,EAAE;AAC3D,aAAU,gBAAgB,EAAE;SACvB;GACL,MAAM,OAAO,gBAAgB;AAC7B,WAAQ,KAAK;AACb,YAAU,iBAA6C,EAAE;AACzD,aAAW,mBAAwC,EAAE;AACrD,OAAI,CAAC,cAAc,KAAK,kBAAkB,CAAC,OAAO,eAChD,UAAS;IAAE,GAAG;IAAQ,gBAAgB,KAAK;IAAgB;;EAI/D,MAAM,EAAE,gBAAgB,GAAG,eAAe;EAC1C,MAAM,QAAQ,QAAQ,WAAW,aAAa,aAAa,iBAAiB,WAAW;EACvF,MAAM,EAAE,SAAS,aAAa,GAAG,cAAc;AAE/C,SAAO,gBAAmB;GACxB,UAAU,KAAK,WAAW,OAAO;IAAE;IAAgB,GAAG;IAAY,CAAC;GACnE,UAAU,EAAE,aAAa,IAAI,OAAO;IAAE;IAAuB;IAAiC,QAAQ;IAAY,SAAS;KAAE;KAAQ,GAAG;KAAa;IAAE,CAAC;GACxJ,SAAS,kBAAkB,OAAO,UAAU;GAC5C,SAAS;IACP,WAAW,UAAU,aAAa,OAAO;IACzC,QAAQ,UAAU,UAAU,OAAO;IACnC,sBAAsB,UAAU,wBAAwB,OAAO;IAC/D,mBAAmB,UAAU,qBAAqB,OAAO;IACzD,iBAAiB,UAAU;IAC3B,6BAA6B,UAAU;IACxC;GACD,oBAAoB,UAAU,sBAAsB;GACpD,mBAAmB,OAAO,KAAK,OAAO,GAAG;GACzC,QAAQ,UAAU;GACnB,CAAC;;CAKJ,SAAS,UACP,IACA,gBACA,cACsB;EACtB,IAAI;EACJ,IAAI;AAGJ,MAAI,mBAAmB,QAAQ,OAAO,mBAAmB,UAAU;AACjE,WAAQ;AACR,aAAU,gBAAgB,EAAE;SACvB;GACL,MAAM,OAAO,gBAAgB;AAC7B,WAAQ,KAAK;AACb,aAAW,kBAAyC,EAAE;AACtD,OAAI,CAAC,cAAc,KAAK,kBAAkB,CAAC,QAAQ,eACjD,WAAU;IAAE,GAAG;IAAS,gBAAgB,KAAK;IAAgB;;EAIjE,MAAM,EAAE,gBAAgB,QAAQ,aAAa,SAAS,aAAa,GAAG,gBAAgB;AAEtF,SAAO,kBAAqB;GAC1B,UAAU,cAAc,CAAC,GAAG,KAAK,OAAO,MAAM,GAAG,EAAE,YAAY,GAAG,KAAK,OAAO,MAAM,GAAG;GACvF,UAAU,EAAE,aAAa,IAAI,QAAQ;IAAM;IAAK;IAAO;IAAgB,QAAQ;IAAa,SAAS;KAAE;KAAQ,GAAG;KAAa;IAAE,CAAC;GAClI,SAAS,CAAC,CAAC,MAAM,kBAAkB,OAAO,YAAY;GACtD,SAAS;IACP,WAAW,YAAY,aAAa,OAAO;IAC3C,QAAQ,YAAY,UAAU,OAAO;IACrC,mBAAmB,YAAY,qBAAqB,OAAO;IAC3D,iBAAiB,YAAY;IAC7B,6BAA6B,YAAY;IAC1C;GACD,QAAQ,YAAY;GACrB,CAAC;;CAKJ,SAAS,aAA+C;EACtD,MAAM,cAAc,gBAAgB;EACpC,MAAM,YAAY,OAAO,MAAM;EAC/B,MAAM,cAAc,kBAAkB,CAAC,UAAU,SAAS,EAAE,CAAC;EAE7D,MAAM,iBAAiB,yBAAyB;GAC9C,aAAa,EAAE,OAAO,gBAAgB,WACpC,IAAI,OAAO;IAAE;IAAO;IAAgB;IAAM,CAAC;GAC7C;GACA,WAAW,CAAC,KAAK,OAAO,CAAC;GACzB;GACA,mBAAmB,SAAS,EAAE,WAAW;IACvC,MAAM,iBAAiB;KACrB,GAAI;KACJ,aAAa;MACZ,UAAU,KAAK,GAAG,OAAO,QAAQ,UAAU,KAAK,IAAI,QAAQ,KAAK,KAAK;KACxE;AACD,WAAO,gBAAgB,UAAU,QAAmB,CAAC,gBAAgB,GAAI,OAAO,EAAE,CAAE,CAAC;;GAEvF,YAAY,MAAM,cAAc;AAC9B,cAAU,UAAU,YAAY,MAAW,EAAE,MAAM,UAAU,MAAM,EAAE,OAAU;;GAEjF,UAAU,OAAO,cAAc;AAC7B,cAAU,UAAU,UAAU,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,OAAU;;GAE3E,YAAY,MAAM,OAAO,cAAc;AACrC,cAAU,UAAU,YAAY,MAAuB,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,OAAU;;GAEpG,UAAU;IAAE,SAAS,OAAO,SAAS;IAAe,OAAO,OAAO,SAAS;IAAa;GACxF,cAAc;GACf,CAAC;EAEF,MAAM,iBAAiB,yBAAyB;GAC9C,aAAa,EAAE,OAAO,gBAAgB,IAAI,WACxC,IAAI,OAAO;IAAE;IAAO;IAAgB;IAAI;IAAM,CAAC;GACjD;GACA,WAAW,CAAC,KAAK,OAAO,CAAC;GACzB;GACA,mBAAmB,SAAS,EAAE,IAAI,WAAW;IAC3C,MAAM,UAAU,gBAAgB,UAAU,SACvC,OAAO,EAAE,EAAE,KAAK,SAAU,UAAU,KAAK,KAAK,KAAK;KAAE,GAAI;KAAiB,GAAI;KAAiB,GAAG,KAAM,CAC1G;AACD,gBAAY,aAAa,KAAK,OAAO,GAAG,GAAG,YACzC,UAAU;KAAE,GAAI;KAAoB,MAAM;MAAE,GAAK,QAA8B,QAAQ,EAAE;MAAG,GAAI;MAAiB;KAAE,GAAG,QACvH;AACD,WAAO;;GAET,YAAY,MAAM,EAAE,IAAI,MAAM,iBAAiB;AAC7C,gBAAY,kBAAkB,EAAE,UAAU,KAAK,OAAO,GAAG,EAAE,CAAC;AAC5D,cAAU,UAAU,YAAY,MAAW;KAAE;KAAI,MAAM;KAAY,EAAE,OAAU;;GAEjF,UAAU,OAAO,EAAE,IAAI,WAAW;AAChC,cAAU,UAAU,UAAU,OAAO;KAAE;KAAI;KAAM,EAAE,OAAU;;GAE/D,YAAY,MAAM,OAAO,EAAE,IAAI,MAAM,iBAAiB;AACpD,cAAU,UAAU,YAAY,MAAuB,OAAO;KAAE;KAAI,MAAM;KAAY,EAAE,OAAU;;GAEpG,UAAU;IAAE,SAAS,OAAO,SAAS;IAAe,OAAO,OAAO,SAAS;IAAa;GACxF,cAAc;GACf,CAAC;EAEF,MAAM,iBAAiB,yBAAyB;GAC9C,aAAa,EAAE,OAAO,gBAAgB,SAAuB,IAAI,OAAO;IAAE;IAAO;IAAgB;IAAI,CAAC;GACtG;GACA,WAAW,CAAC,KAAK,OAAO,CAAC;GACzB;GACA,mBAAmB,SAAS,EAAE,SAAS;AACrC,gBAAY,cAAc,EAAE,UAAU,KAAK,OAAO,GAAG,EAAE,CAAC;AACxD,WAAO,gBAAgB,UAAU,SAAoB,OAAO,EAAE,EAAE,QAAQ,SAAS,UAAU,KAAK,KAAK,GAAG,CAAC;;GAE3G,YAAY,MAAM,EAAE,SAAS;AAC3B,cAAU,UAAU,YAAY,MAAM,EAAE,IAAI,EAAE,OAAU;;GAE1D,UAAU,OAAO,EAAE,SAAS;AAC1B,cAAU,UAAU,UAAU,OAAO,EAAE,IAAI,EAAE,OAAU;;GAEzD,YAAY,MAAM,OAAO,EAAE,SAAS;AAClC,cAAU,UAAU,YAAY,MAAM,OAAO,EAAE,IAAI,EAAE,OAAU;;GAEjE,UAAU;IAAE,SAAS,OAAO,SAAS;IAAe,OAAO,OAAO,SAAS;IAAa;GACxF,cAAc;GACf,CAAC;EAEF,MAAM,eAAoF,WAAiB;GACzG,MAAM,OAAO,gBAAgB;AAC7B,UAAO;IACL,GAAG;IACH,OAAO,OAAO,SAAS,KAAK;IAC5B,gBAAgB,aAAc,OAAO,kBAAkB,OAAS,OAAO,kBAAkB,KAAK;IAC/F;;EAGH,MAAM,SAAS,OAAO,QAAiC,YAAyC;AAC9F,aAAU,UAAU,SAAS,UAAU;AACvC,OAAI;IACF,MAAM,SAAS,MAAM,eAAe,YAAY,YAAY,OAAO,CAAC;AACpE,aAAS,YAAY,OAAY;AACjC,aAAS,YAAY,QAAa,KAAK;AACvC,WAAO;YACA,OAAO;AACd,aAAS,UAAU,MAAe;AAClC,aAAS,YAAY,QAAW,MAAe;AAC/C,UAAM;aACE;AACR,cAAU,UAAU;;;EAIxB,MAAM,SAAS,OAAO,QAA+B,YAAyC;AAC5F,aAAU,UAAU,SAAS,UAAU;AACvC,OAAI;IACF,MAAM,SAAS,MAAM,eAAe,YAAY,YAAY,OAAO,CAAC;AACpE,aAAS,YAAY,OAAY;AACjC,aAAS,YAAY,QAAa,KAAK;AACvC,WAAO;YACA,OAAO;AACd,aAAS,UAAU,MAAe;AAClC,aAAS,YAAY,QAAW,MAAe;AAC/C,UAAM;aACE;AACR,cAAU,UAAU;;;EAIxB,MAAM,SAAS,OAAO,QAAsB,YAA4C;AACtF,aAAU,UAAU,SAAS,UAAU;AACvC,OAAI;IACF,MAAM,SAAS,MAAM,eAAe,YAAY,YAAY,OAAO,CAAC;AACpE,aAAS,YAAY,OAAO;AAC5B,aAAS,YAAY,QAAQ,KAAK;AAClC,WAAO;YACA,OAAO;AACd,aAAS,UAAU,MAAe;AAClC,aAAS,YAAY,QAAW,MAAe;AAC/C,UAAM;aACE;AACR,cAAU,UAAU;;;AAIxB,SAAO;GACL;GACA;GACA;GACA,YAAY,eAAe;GAC3B,YAAY,eAAe;GAC3B,YAAY,eAAe;GAC3B,YAAY,eAAe,aAAa,eAAe,aAAa,eAAe;GACpF;;CAKH,SAAS,gBACP,eACA,iBACA,cAC4B;EAC5B,IAAI;EACJ,IAAI;EACJ,IAAI;AAEJ,MAAI,kBAAkB,QAAQ,OAAO,kBAAkB,UAAU;AAC/D,WAAQ;AACR,YAAU,mBAA+C,EAAE;AAC3D,aAAU,gBAAgB,EAAE;SACvB;GACL,MAAM,OAAO,gBAAgB;AAC7B,WAAQ,KAAK;AACb,YAAU,iBAA6C,EAAE;AACzD,aAAW,mBAAgD,EAAE;AAC7D,OAAI,CAAC,cAAc,KAAK,kBAAkB,CAAC,OAAO,eAChD,UAAS;IAAE,GAAG;IAAQ,gBAAgB,KAAK;IAAgB;;EAI/D,MAAM,EAAE,gBAAgB,GAAG,eAAe;EAC1C,MAAM,QAAQ,QAAQ,WAAW,iBAAiB,WAAW;EAC7D,MAAM,EAAE,SAAS,aAAa,GAAG,cAAc;AAE/C,SAAO,wBAA2B;GAChC,UAAU,CAAC,GAAG,KAAK,WAAW,OAAO;IAAE;IAAgB,GAAG;IAAY,CAAC,EAAE,WAAW;GACpF,UAAU,EAAE,WAAW,aAAa;IAClC,MAAM,mBAAmB,OAAO,cAAc,WAC1C,EAAE,OAAO,WAAW,GACpB,EAAE,MAAM,WAAW;AAEvB,WAAO,IAAI,OAAO;KAChB;KACgB;KAChB,QAAQ;MAAE,GAAG;MAAY,GAAG;MAAkB;KAC9C,SAAS;MAAE;MAAQ,GAAG;MAAa;KACpC,CAAC;;GAEJ,SAAS,kBAAkB,OAAO,UAAU;GAC5C,kBAAkB,WAAW,QAAQ,WAAW,QAAQ;GACxD,mBAAmB,aAAa;IAC9B,MAAM,OAAO;AACb,QAAI,mBAAmB,KAAK,CAC1B,QAAO,KAAK,UAAU,KAAK,OAAO;AAEpC,QAAI,mBAAmB,KAAK,CAC1B,QAAO,KAAK,UAAU,KAAK,OAAO,IAAI;IAGxC,MAAM,IAAI;AACV,QAAI,OAAO,EAAE,YAAY,aAAa,OAAO,EAAE,SAAS,SACtD,QAAO,EAAE,UAAW,EAAE,OAAkB,IAAI;;GAIhD,SAAS;IACP,WAAW,UAAU,aAAa,OAAO;IACzC,QAAQ,UAAU,UAAU,OAAO;IACnC,sBAAsB,UAAU,wBAAwB,OAAO;IAC/D,mBAAmB,UAAU,qBAAqB,OAAO;IAC1D;GACF,CAAC;;CAKJ,SAAS,UAAU,SAMhB;AACD,MAAI,CAAC,IAAI,OACP,OAAM,IAAI,MAAM,eAAe,UAAU,wCAAwC;EAGnF,MAAM,YAAY,IAAI;AAEtB,SAAO,0BAAmF;GACxF,aAAa,EAAE,MAAM,IAAI,WAAW;IAClC,MAAM,OAAO,gBAAgB;AAC7B,WAAO,UAAU;KAAE,OAAO,KAAK;KAAO,gBAAgB,aAAa,OAAO,KAAK;KAAgB;KAAM;KAAI;KAAM,CAAC;;GAElH,mBAAmB,SAAS,qBAAqB,CAAC,KAAK,OAAO,CAAC;GAC/D,YAAY,SAAS,SAAS,YAAY,KAAK;GAC/C,UAAU,UAAU,SAAS,UAAU,MAAM;GAC7C,YAAY,MAAM,UAAU,SAAS,YAAY,MAAM,MAAM;GAC7D,UAAU,SAAS,YAAY;IAC7B,SAAS,GAAG,SAAS;IACrB,OAAO,oBAAoB,SAAS,aAAa;IAClD;GACD,cAAc;GACf,CAAC;;CAKJ,SAAS,UACP,OACA,QACA,SACoB;AACpB,MAAI,CAAC,IAAI,OACP,OAAM,IAAI,MAAM,eAAe,UAAU,uCAAuC;EAGlF,MAAM,YAAY,IAAI;EACtB,MAAM,OAAO,gBAAgB;EAC7B,MAAM,QAAQ,KAAK;EACnB,MAAM,iBAAiB,iBAAiB,OAAQ,QAAQ,kBAAmC,KAAK;EAChG,MAAM,EAAE,gBAAgB,GAAG,GAAG,eAAe,UAAU,EAAE;EACzD,MAAM,eAAe;GAAE,GAAG;GAAO,GAAG;GAAY;EAChD,MAAM,EAAE,SAAS,aAAa,GAAG,cAAc,WAAW,EAAE;EAG5D,MAAM,kBAAkB,iBACpB;GAAE;GAAgB,GAAG;GAAc,GACnC;AAEJ,SAAO,gBAAmB;GACxB,UAAU;IAAC,GAAG,KAAK,OAAO;IAAE;IAAU;IAAgB;GACtD,UAAU,EAAE,aAAa,UAAU;IACjC;IACA;IACA,QAAQ;IACR,SAAS;KAAE;KAAQ,GAAG;KAAa;IACpC,CAAC;GACF,SAAS,MAAM,SAAS,KAAK,kBAAkB,OAAO,UAAU;GAChE,SAAS;IACP,WAAW,UAAU,aAAa,OAAO;IACzC,QAAQ,UAAU,UAAU,OAAO;IACpC;GACD,QAAQ,UAAU;GACnB,CAAC;;CAKJ,SAAS,kBAAyD,gBAO/D;AACD,SAAO,0BAA6C;GAClD,YAAY,eAAe;GAC3B,mBAAmB,eAAe,qBAAqB,CAAC,KAAK,OAAO,CAAC;GACrE,WAAW,eAAe;GAC1B,SAAS,eAAe;GACxB,WAAW,eAAe;GAC1B,UAAU,eAAe;GACzB,cAAc;GACf,CAAC;;CAKJ,SAAS,gBAA+B;EACtC,MAAM,cAAc,gBAAgB;EAEpC,MAAM,UADmB,sBAAsB,kBACZ;AAEnC,SAAO,aACJ,MAAc,MAAS,UAA6B,EAAE,KAAK;GAC1D,MAAM,KAAK,UAAU,KAAK;AAC1B,OAAI,GACF,aAAY,aAAa,KAAK,OAAO,GAAG,EAAE,EAAE,MAAM,MAAM,CAAC;AAG3D,OAAI,CAAC,OAAQ;GAEb,MAAM,EAAE,SAAS,MAAM,UAAU,UAAU;AAC3C,OAAI,QACF,QAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC;OAEhC,QAAO,KAAK,MAAM,EAAE,QAAQ,CAAC;KAGjC,CAAC,aAAa,OAAO,CACtB;;AAGH,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/arc-next",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "React + TanStack Query SDK for Arc resources",
5
5
  "type": "module",
6
6
  "sideEffects": false,