@classytic/arc-next 0.8.0 → 0.9.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
@@ -1,4 +1,4 @@
1
- import { ArcClient } from "./client.js";
1
+ import { ArcClient, NextFetchOptions } from "./client.js";
2
2
  import { AggregatePaginationResult, KeysetPaginationResult, OffsetPaginationResult, PaginatedResult } from "@classytic/repo-core/pagination";
3
3
  import { AggResult, AggRow, BulkCreateResult, DeleteManyResult, DeleteResult, UpdateManyResult } from "@classytic/repo-core/repository";
4
4
  import { BracketOperator, BracketOperator as BracketOperator$1 } from "@classytic/repo-core/query-parser";
@@ -50,8 +50,14 @@ interface RequestOptions {
50
50
  token?: string | null;
51
51
  organizationId?: string | null;
52
52
  cache?: RequestCache;
53
- revalidate?: number;
53
+ /** Flattened Next `revalidate`. `false` = cache indefinitely. */
54
+ revalidate?: number | false;
54
55
  tags?: string[];
56
+ /**
57
+ * Idiomatic Next App Router fetch config — passed to `fetch(url, { next })`.
58
+ * Merged with the flattened `revalidate`/`tags`. Prefer this from Next hosts.
59
+ */
60
+ next?: NextFetchOptions;
55
61
  headerOptions?: Record<string, string>;
56
62
  responseType?: 'json' | 'blob' | 'text';
57
63
  signal?: AbortSignal;
@@ -87,6 +93,23 @@ declare class BaseApi<TDoc = Record<string, unknown>, TCreate = Partial<TDoc>, T
87
93
  constructor(entity: string, config?: BaseApiConfig);
88
94
  /** Merge per-instance headers into request options */
89
95
  private withHeaders;
96
+ /**
97
+ * Apply the instance's default `cache` to a per-call options object — but
98
+ * ONLY when the caller expressed no caching intent of their own.
99
+ *
100
+ * A per-call `revalidate`/`next` (time-based ISR) or an explicit `cache`
101
+ * takes precedence. The default is `no-store`; forcing it alongside a
102
+ * `revalidate` makes Next.js throw ("cache: 'no-store' and revalidate are
103
+ * contradictory") and otherwise silently pins the route to dynamic
104
+ * rendering — so a consumer can never opt a single read into ISR. Gating the
105
+ * default here lets `getBySlug({ slug, options: { revalidate: 60 } })` become
106
+ * statically cacheable without every other call losing its no-store default.
107
+ *
108
+ * Framework-agnostic: `cache` / `revalidate` / `next` are inert pass-throughs
109
+ * on runtimes (React Native, plain browser fetch) that don't implement the
110
+ * Next.js fetch extensions, so this never assumes a Next host.
111
+ */
112
+ private withCacheDefault;
90
113
  createQueryString(params?: Record<string, unknown>): string;
91
114
  prepareParams(params?: QueryParams): Record<string, unknown>;
92
115
  getAll({
@@ -259,8 +282,16 @@ declare class BaseApi<TDoc = Record<string, unknown>, TCreate = Partial<TDoc>, T
259
282
  }
260
283
  declare function createCrudApi<TDoc = Record<string, unknown>, TCreate = Partial<TDoc>, TUpdate = Partial<TDoc>>(entity: string, config?: BaseApiConfig): BaseApi<TDoc, TCreate, TUpdate>;
261
284
  type ExtractDoc<T> = T extends PaginatedResult<infer D> ? D : never;
285
+ /** Any preset-augmented BaseApi — the constraint preset factories accept. */
286
+ type AnyBaseApi = BaseApi<any, any, any>;
287
+ /** Document type of a (possibly augmented) BaseApi. */
288
+ type DocOf<A> = A extends BaseApi<infer D, any, any> ? D : never;
289
+ /** Create-payload type of a (possibly augmented) BaseApi. */
290
+ type CreateOf<A> = A extends BaseApi<any, infer C, any> ? C : never;
291
+ /** Update-payload type of a (possibly augmented) BaseApi. */
292
+ type UpdateOf<A> = A extends BaseApi<any, any, infer U> ? U : never;
262
293
  declare function isOffsetPagination<T>(response: PaginatedResult<T>): response is OffsetPaginationResult<T>;
263
294
  declare function isKeysetPagination<T>(response: PaginatedResult<T>): response is KeysetPaginationResult<T>;
264
295
  declare function isAggregatePagination<T>(response: PaginatedResult<T>): response is AggregatePaginationResult<T>;
265
296
  //#endregion
266
- export { type AggResult, type AggRow, BaseApi, BaseApiConfig, type BracketOperator, type BulkCreateResult, type DeleteManyResult, type DeleteResult, ExtractDoc, FilterOperator, PopulateOption, QueryParams, RequestOptions, ScopedArgs, SortDirection, SortSpec, type UpdateManyResult, createCrudApi, isAggregatePagination, isKeysetPagination, isOffsetPagination };
297
+ export { type AggResult, type AggRow, AnyBaseApi, BaseApi, BaseApiConfig, type BracketOperator, type BulkCreateResult, CreateOf, type DeleteManyResult, type DeleteResult, DocOf, ExtractDoc, FilterOperator, PopulateOption, QueryParams, RequestOptions, ScopedArgs, SortDirection, SortSpec, type UpdateManyResult, UpdateOf, createCrudApi, isAggregatePagination, isKeysetPagination, isOffsetPagination };
package/dist/api.js CHANGED
@@ -33,6 +33,29 @@ var BaseApi = class {
33
33
  }
34
34
  };
35
35
  }
36
+ /**
37
+ * Apply the instance's default `cache` to a per-call options object — but
38
+ * ONLY when the caller expressed no caching intent of their own.
39
+ *
40
+ * A per-call `revalidate`/`next` (time-based ISR) or an explicit `cache`
41
+ * takes precedence. The default is `no-store`; forcing it alongside a
42
+ * `revalidate` makes Next.js throw ("cache: 'no-store' and revalidate are
43
+ * contradictory") and otherwise silently pins the route to dynamic
44
+ * rendering — so a consumer can never opt a single read into ISR. Gating the
45
+ * default here lets `getBySlug({ slug, options: { revalidate: 60 } })` become
46
+ * statically cacheable without every other call losing its no-store default.
47
+ *
48
+ * Framework-agnostic: `cache` / `revalidate` / `next` are inert pass-throughs
49
+ * on runtimes (React Native, plain browser fetch) that don't implement the
50
+ * Next.js fetch extensions, so this never assumes a Next host.
51
+ */
52
+ withCacheDefault(options = {}) {
53
+ if (options.cache !== void 0 || options.revalidate !== void 0 || options.next !== void 0) return options;
54
+ return {
55
+ cache: this.config.cache,
56
+ ...options
57
+ };
58
+ }
36
59
  createQueryString(params = {}) {
37
60
  return createQueryString(params);
38
61
  }
@@ -77,10 +100,7 @@ var BaseApi = class {
77
100
  };
78
101
  const processedParams = this.prepareParams(mergedParams);
79
102
  const queryString = this.createQueryString(processedParams);
80
- const requestOptions = {
81
- cache: this.config.cache,
82
- ...options
83
- };
103
+ const requestOptions = { ...this.withCacheDefault(options) };
84
104
  if (token) requestOptions.token = token;
85
105
  if (organizationId) requestOptions.organizationId = organizationId;
86
106
  return this.requestFn("GET", `${this.baseUrl}?${queryString}`, this.withHeaders(requestOptions));
@@ -89,10 +109,7 @@ var BaseApi = class {
89
109
  if (!id) throw new Error("ID is required");
90
110
  const queryString = this.createQueryString(params);
91
111
  const url = queryString ? `${this.baseUrl}/${id}?${queryString}` : `${this.baseUrl}/${id}`;
92
- const requestOptions = {
93
- cache: this.config.cache,
94
- ...options
95
- };
112
+ const requestOptions = { ...this.withCacheDefault(options) };
96
113
  if (token) requestOptions.token = token;
97
114
  if (organizationId) requestOptions.organizationId = organizationId;
98
115
  return this.requestFn("GET", url, this.withHeaders(requestOptions));
@@ -142,8 +159,7 @@ var BaseApi = class {
142
159
  }
143
160
  const requestOptions = {
144
161
  body: data,
145
- cache: this.config.cache,
146
- ...options
162
+ ...this.withCacheDefault(options)
147
163
  };
148
164
  if (token) requestOptions.token = token;
149
165
  if (organizationId) requestOptions.organizationId = organizationId;
package/dist/client.d.ts CHANGED
@@ -602,13 +602,40 @@ interface TextResponse {
602
602
  data: string;
603
603
  response: Response;
604
604
  }
605
+ /**
606
+ * Next.js App Router `fetch` cache directives — forwarded verbatim as
607
+ * `fetch(url, { next })`. This is the idiomatic Next shape; a host using the
608
+ * App Router can pass it 1:1 with what they'd hand to `fetch`. The flattened
609
+ * `revalidate` / `tags` options remain for back-compat and are merged into
610
+ * this object before the request (flattened values win / append).
611
+ *
612
+ * @see https://nextjs.org/docs/app/api-reference/functions/fetch
613
+ */
614
+ interface NextFetchOptions {
615
+ /**
616
+ * Seconds before the cached response is considered stale and revalidated.
617
+ * `false` caches indefinitely (Next's `force-cache` semantics); `0` opts
618
+ * out of caching. Omit to inherit the route's default.
619
+ */
620
+ revalidate?: number | false;
621
+ /** Cache tags for on-demand `revalidateTag(tag)` invalidation. */
622
+ tags?: string[];
623
+ }
605
624
  interface ApiRequestOptions {
606
625
  body?: unknown;
607
626
  token?: string | null;
608
627
  organizationId?: string | null;
609
- revalidate?: number;
628
+ /** Flattened Next `revalidate` (see `next`). `false` = cache indefinitely. */
629
+ revalidate?: number | false;
610
630
  headerOptions?: Record<string, string>;
631
+ /** Flattened Next cache `tags` (see `next`). */
611
632
  tags?: string[];
633
+ /**
634
+ * Idiomatic Next App Router fetch cache config — passed straight to
635
+ * `fetch(url, { next })`. Prefer this over the flattened `revalidate`/`tags`
636
+ * when a Next host wants full control; both are merged.
637
+ */
638
+ next?: NextFetchOptions;
612
639
  cache?: RequestCache;
613
640
  signal?: AbortSignal;
614
641
  /** Explicit idempotency key for this request. Sent as `Idempotency-Key` header. */
@@ -765,10 +792,12 @@ interface ArcFetchOptions extends Omit<RequestInit, 'body' | 'headers'> {
765
792
  elevated?: boolean;
766
793
  /** Per-call `Idempotency-Key` header. */
767
794
  idempotencyKey?: string;
768
- /** Next.js fetch `revalidate` pass-through. */
769
- revalidate?: number;
770
- /** Next.js fetch `tags` pass-through. */
795
+ /** Flattened Next `revalidate` pass-through. `false` = cache indefinitely. */
796
+ revalidate?: number | false;
797
+ /** Flattened Next cache `tags` pass-through. */
771
798
  tags?: string[];
799
+ /** Idiomatic Next App Router fetch config — merged with `revalidate`/`tags`. */
800
+ next?: NextFetchOptions;
772
801
  /** `cache` pass-through (browser fetch + Next.js). */
773
802
  cache?: RequestCache;
774
803
  /**
@@ -835,4 +864,4 @@ declare const arc: {
835
864
  delete: <T = unknown>(path: string, opts?: ArcFetchOptions) => Promise<T>;
836
865
  };
837
866
  //#endregion
838
- export { AfterResponseContext, AfterResponseInterceptor, ApiRequestOptions, ArcApiError, ArcApiErrorOptions, ArcClient, ArcClientConfig, ArcErrorCode, ArcFetchOptions, AuthConfig, AuthErrorContext, AuthErrorHandler, BeforeRequestContext, BeforeRequestInterceptor, BlobResponse, ClientConfig, ClientEncryptionConfig, HttpMethod, KNOWN_ARC_ERROR_CODES, RetryConfig, StreamUrlProtocol, TextResponse, ToastHandler, UseRouterHook, _getAuthErrorHandler, _isAuthRecoverable, _resetArcFetchClient, _resetAuthRecovery, _resetAuthWarnings, _resolveRefreshedToken, _runAuthRecovery, arc, arcAuthHeaders, arcFetch, buildStreamUrl, configureAuth, configureClient, createAuthAwareClient, createAuthRefreshHandler, createClient, createQueryString, getAuthContext, getAuthMode, getBaseUrl, getClientAuthContext, handleApiRequest, hasGlobalStaticAuth, isAbortError, isArcApiError, isArcErrorCode, isAutoIdempotency, isDuplicateKeyError, isOrgContextRequiredError, isValidationError };
867
+ export { AfterResponseContext, AfterResponseInterceptor, ApiRequestOptions, ArcApiError, ArcApiErrorOptions, ArcClient, ArcClientConfig, ArcErrorCode, ArcFetchOptions, AuthConfig, AuthErrorContext, AuthErrorHandler, BeforeRequestContext, BeforeRequestInterceptor, BlobResponse, ClientConfig, ClientEncryptionConfig, HttpMethod, KNOWN_ARC_ERROR_CODES, NextFetchOptions, RetryConfig, StreamUrlProtocol, TextResponse, ToastHandler, UseRouterHook, _getAuthErrorHandler, _isAuthRecoverable, _resetArcFetchClient, _resetAuthRecovery, _resetAuthWarnings, _resolveRefreshedToken, _runAuthRecovery, arc, arcAuthHeaders, arcFetch, buildStreamUrl, configureAuth, configureClient, createAuthAwareClient, createAuthRefreshHandler, createClient, createQueryString, getAuthContext, getAuthMode, getBaseUrl, getClientAuthContext, handleApiRequest, hasGlobalStaticAuth, isAbortError, isArcApiError, isArcErrorCode, isAutoIdempotency, isDuplicateKeyError, isOrgContextRequiredError, isValidationError };
package/dist/client.js CHANGED
@@ -738,7 +738,7 @@ function sleepAbortable(ms, signal) {
738
738
  }
739
739
  /** A single fetch attempt — used by executeRequest's retry loop. */
740
740
  async function executeAttempt(config, method, endpoint, options, attempt) {
741
- const { body, token, organizationId, revalidate, headerOptions, tags, cache, signal, idempotencyKey, elevated } = options;
741
+ const { body, token, organizationId, revalidate, headerOptions, tags, next, cache, signal, idempotencyKey, elevated } = options;
742
742
  const startTime = Date.now();
743
743
  try {
744
744
  let headers = {
@@ -788,14 +788,10 @@ async function executeAttempt(config, method, endpoint, options, attempt) {
788
788
  };
789
789
  if (serializedBody !== void 0) fetchOptions.body = serializedBody;
790
790
  if (cache) fetchOptions.cache = cache;
791
- if (revalidate !== void 0) fetchOptions.next = {
792
- ...fetchOptions.next,
793
- revalidate
794
- };
795
- if (tags) fetchOptions.next = {
796
- ...fetchOptions.next,
797
- tags
798
- };
791
+ const nextCfg = { ...next };
792
+ if (revalidate !== void 0) nextCfg.revalidate = revalidate;
793
+ if (tags) nextCfg.tags = nextCfg.tags ? [...nextCfg.tags, ...tags] : tags;
794
+ if (nextCfg.revalidate !== void 0 || nextCfg.tags) fetchOptions.next = nextCfg;
799
795
  if (!/^https?:\/\//i.test(endpoint) && !config.baseUrl) throw new Error(`[arc-next] handleApiRequest(${method} ${endpoint}): baseUrl is empty. Call configureClient({ baseUrl: '...' }) BEFORE the first request. If you use createAuthAwareClient() at module top-level, make sure the Providers component runs configureClient() first (e.g. in a useState() initializer, before the children render).`);
800
796
  const response = await fetch(`${config.baseUrl}${endpoint}`, fetchOptions);
801
797
  if (!response.ok) {
@@ -1062,7 +1058,7 @@ function sanitizeUserHeaders(headers) {
1062
1058
  * const result = await arc.post<{ ok: true }>('/api/statements', statements);
1063
1059
  */
1064
1060
  function arcFetch(path, options = {}) {
1065
- const { method = "GET", body, headers, signal, elevated, idempotencyKey, revalidate, tags, cache, client } = options;
1061
+ const { method = "GET", body, headers, signal, elevated, idempotencyKey, revalidate, tags, next, cache, client } = options;
1066
1062
  const transport = client ?? getDefaultArcFetchClient();
1067
1063
  const apiOptions = {
1068
1064
  body,
@@ -1072,6 +1068,7 @@ function arcFetch(path, options = {}) {
1072
1068
  ...idempotencyKey ? { idempotencyKey } : {},
1073
1069
  ...revalidate !== void 0 ? { revalidate } : {},
1074
1070
  ...tags ? { tags } : {},
1071
+ ...next ? { next } : {},
1075
1072
  ...cache ? { cache } : {}
1076
1073
  };
1077
1074
  return transport.request(method, path, apiOptions);
@@ -11,7 +11,24 @@ interface PrefetchAuthContext {
11
11
  }
12
12
  interface PrefetchOptions extends PrefetchAuthContext {
13
13
  staleTime?: number;
14
+ /**
15
+ * Next.js fetch caching forwarded to the underlying API call. A Server
16
+ * Component that prefetches with `revalidate` lets that data participate in
17
+ * ISR — without it the SDK's default `no-store` pins the whole route to
18
+ * dynamic rendering (e.g. a shared layout prefetch silently disables ISR on
19
+ * every page under it). Inert off-Next (React Native / plain browser fetch).
20
+ */
21
+ cache?: RequestCache;
22
+ revalidate?: number | false;
23
+ tags?: string[];
14
24
  }
25
+ /** Per-call API `options` the prefetcher forwards (caching + custom headers). */
26
+ type ForwardedApiOptions = {
27
+ headerOptions?: Record<string, string>;
28
+ cache?: RequestCache;
29
+ revalidate?: number | false;
30
+ tags?: string[];
31
+ };
15
32
  interface PrefetchDetailOptions extends PrefetchOptions {
16
33
  /** Query params (select, populate) — key must match useDetail's params to share cache */
17
34
  params?: {
@@ -107,51 +124,39 @@ declare function createCrudPrefetcher(api: {
107
124
  params?: Record<string, unknown>;
108
125
  token?: string | null;
109
126
  organizationId?: string | null;
110
- options?: {
111
- headerOptions?: Record<string, string>;
112
- };
127
+ options?: ForwardedApiOptions;
113
128
  }) => Promise<unknown>;
114
129
  getById: (opts: {
115
130
  id: string;
116
131
  token?: string | null;
117
132
  organizationId?: string | null;
118
- options?: {
119
- headerOptions?: Record<string, string>;
120
- };
133
+ options?: ForwardedApiOptions;
121
134
  }) => Promise<unknown>;
122
135
  getBySlug?: (opts: {
123
136
  slug: string;
124
137
  token?: string | null;
125
138
  organizationId?: string | null;
126
139
  params?: Record<string, unknown>;
127
- options?: {
128
- headerOptions?: Record<string, string>;
129
- };
140
+ options?: ForwardedApiOptions;
130
141
  }) => Promise<unknown>;
131
142
  getDeleted?: (opts: {
132
143
  params?: Record<string, unknown>;
133
144
  token?: string | null;
134
145
  organizationId?: string | null;
135
- options?: {
136
- headerOptions?: Record<string, string>;
137
- };
146
+ options?: ForwardedApiOptions;
138
147
  }) => Promise<unknown>;
139
148
  aggregate?: (opts: {
140
149
  name: string;
141
150
  filter?: Record<string, unknown>;
142
151
  token?: string | null;
143
152
  organizationId?: string | null;
144
- options?: {
145
- headerOptions?: Record<string, string>;
146
- };
153
+ options?: ForwardedApiOptions;
147
154
  }) => Promise<unknown>;
148
155
  getTree?: (opts: {
149
156
  params?: Record<string, unknown>;
150
157
  token?: string | null;
151
158
  organizationId?: string | null;
152
- options?: {
153
- headerOptions?: Record<string, string>;
154
- };
159
+ options?: ForwardedApiOptions;
155
160
  }) => Promise<unknown>;
156
161
  }, entityKey: string): CrudPrefetcher;
157
162
  //#endregion
package/dist/prefetch.js CHANGED
@@ -29,6 +29,14 @@ import { HydrationBoundary, dehydrate } from "@tanstack/react-query";
29
29
  */
30
30
  function createCrudPrefetcher(api, entityKey) {
31
31
  const KEYS = createQueryKeys(entityKey);
32
+ const apiOptions = (o) => {
33
+ const opt = {};
34
+ if (o.headers) opt.headerOptions = o.headers;
35
+ if (o.cache !== void 0) opt.cache = o.cache;
36
+ if (o.revalidate !== void 0) opt.revalidate = o.revalidate;
37
+ if (o.tags !== void 0) opt.tags = o.tags;
38
+ return Object.keys(opt).length ? { options: opt } : {};
39
+ };
32
40
  return {
33
41
  async prefetchList(queryClient, params = {}, options = {}) {
34
42
  const { organizationId: paramOrgId, ...restParams } = params;
@@ -44,7 +52,7 @@ function createCrudPrefetcher(api, entityKey) {
44
52
  params: restParams,
45
53
  token: options.token ?? null,
46
54
  organizationId: orgId,
47
- ...options.headers ? { options: { headerOptions: options.headers } } : {}
55
+ ...apiOptions(options)
48
56
  }),
49
57
  staleTime: options.staleTime
50
58
  });
@@ -60,7 +68,7 @@ function createCrudPrefetcher(api, entityKey) {
60
68
  token: token ?? null,
61
69
  organizationId: organizationId ?? null,
62
70
  ...params ? { params } : {},
63
- ...options.headers ? { options: { headerOptions: options.headers } } : {}
71
+ ...apiOptions(options)
64
72
  }),
65
73
  staleTime
66
74
  });
@@ -76,7 +84,7 @@ function createCrudPrefetcher(api, entityKey) {
76
84
  token: token ?? null,
77
85
  organizationId: organizationId ?? null,
78
86
  ...params ? { params } : {},
79
- ...options.headers ? { options: { headerOptions: options.headers } } : {}
87
+ ...apiOptions(options)
80
88
  }),
81
89
  staleTime
82
90
  });
@@ -95,7 +103,7 @@ function createCrudPrefetcher(api, entityKey) {
95
103
  params: restParams,
96
104
  token: options.token ?? null,
97
105
  organizationId: orgId,
98
- ...options.headers ? { options: { headerOptions: options.headers } } : {}
106
+ ...apiOptions(options)
99
107
  }),
100
108
  staleTime: options.staleTime
101
109
  });
@@ -115,7 +123,7 @@ function createCrudPrefetcher(api, entityKey) {
115
123
  filter,
116
124
  token: options.token ?? null,
117
125
  organizationId: orgId,
118
- ...options.headers ? { options: { headerOptions: options.headers } } : {}
126
+ ...apiOptions(options)
119
127
  }),
120
128
  staleTime: options.staleTime
121
129
  });
@@ -134,7 +142,7 @@ function createCrudPrefetcher(api, entityKey) {
134
142
  params: restParams,
135
143
  token: options.token ?? null,
136
144
  organizationId: orgId,
137
- ...options.headers ? { options: { headerOptions: options.headers } } : {}
145
+ ...apiOptions(options)
138
146
  }),
139
147
  staleTime: options.staleTime
140
148
  });
@@ -156,7 +164,7 @@ function createCrudPrefetcher(api, entityKey) {
156
164
  },
157
165
  token: options.token ?? null,
158
166
  organizationId: orgId,
159
- ...options.headers ? { options: { headerOptions: options.headers } } : {}
167
+ ...apiOptions(options)
160
168
  }),
161
169
  initialPageParam: 1,
162
170
  getNextPageParam: () => void 0,
@@ -1,4 +1,4 @@
1
- import { BaseApi, ScopedArgs } from "../api.js";
1
+ import { AnyBaseApi, CreateOf, DocOf, ScopedArgs, UpdateOf } from "../api.js";
2
2
  import { BulkCreateResult, DeleteManyResult, UpdateManyResult } from "@classytic/repo-core/repository";
3
3
 
4
4
  //#region src/presets/bulk.d.ts
@@ -38,6 +38,6 @@ interface BulkMethods<TDoc, TCreate = Partial<TDoc>, TUpdate = Partial<TDoc>> {
38
38
  * await todos.bulkUpdate({ filter: { status: 'pending' }, data: { status: 'archived' } });
39
39
  * await todos.bulkDelete({ filter: { archivedBefore: '2024-01-01' } });
40
40
  */
41
- declare function withBulk<TDoc, TCreate, TUpdate>(api: BaseApi<TDoc, TCreate, TUpdate>): BaseApi<TDoc, TCreate, TUpdate> & BulkMethods<TDoc, TCreate, TUpdate>;
41
+ declare function withBulk<TApi extends AnyBaseApi>(api: TApi): TApi & BulkMethods<DocOf<TApi>, CreateOf<TApi>, UpdateOf<TApi>>;
42
42
  //#endregion
43
43
  export { BulkMethods, withBulk };
@@ -1,4 +1,4 @@
1
- import { BaseApi, ScopedArgs } from "../api.js";
1
+ import { AnyBaseApi, DocOf, ScopedArgs } from "../api.js";
2
2
  import { PaginatedResult } from "@classytic/repo-core/pagination";
3
3
 
4
4
  //#region src/presets/search.d.ts
@@ -51,6 +51,6 @@ interface SearchPresetMethods<TDoc> {
51
51
  * await places.searchSimilar({ vector: [0.1, 0.2, ...], body: { topK: 5 } });
52
52
  * await places.embed({ input: 'hello world' });
53
53
  */
54
- declare function withSearchPreset<TDoc, TCreate, TUpdate>(api: BaseApi<TDoc, TCreate, TUpdate>): BaseApi<TDoc, TCreate, TUpdate> & SearchPresetMethods<TDoc>;
54
+ declare function withSearchPreset<TApi extends AnyBaseApi>(api: TApi): TApi & SearchPresetMethods<DocOf<TApi>>;
55
55
  //#endregion
56
56
  export { SearchPresetMethods, withSearchPreset };
@@ -1,4 +1,4 @@
1
- import { BaseApi, ScopedArgs } from "../api.js";
1
+ import { AnyBaseApi, DocOf, ScopedArgs } from "../api.js";
2
2
 
3
3
  //#region src/presets/slug.d.ts
4
4
  interface SlugLookupMethods<TDoc> {
@@ -23,6 +23,6 @@ interface SlugLookupMethods<TDoc> {
23
23
  *
24
24
  * const cat = await categories.getBySlug({ slug: 'engineering' });
25
25
  */
26
- declare function withSlugLookup<TDoc, TCreate, TUpdate>(api: BaseApi<TDoc, TCreate, TUpdate>): BaseApi<TDoc, TCreate, TUpdate> & SlugLookupMethods<TDoc>;
26
+ declare function withSlugLookup<TApi extends AnyBaseApi>(api: TApi): TApi & SlugLookupMethods<DocOf<TApi>>;
27
27
  //#endregion
28
28
  export { SlugLookupMethods, withSlugLookup };
@@ -1,4 +1,4 @@
1
- import { BaseApi, QueryParams, ScopedArgs } from "../api.js";
1
+ import { AnyBaseApi, DocOf, QueryParams, ScopedArgs } from "../api.js";
2
2
  import { PaginatedResult } from "@classytic/repo-core/pagination";
3
3
 
4
4
  //#region src/presets/soft-delete.d.ts
@@ -29,6 +29,6 @@ interface SoftDeleteMethods<TDoc> {
29
29
  * await todos.restore({ id }); // undo
30
30
  * const trash = await todos.getDeleted();
31
31
  */
32
- declare function withSoftDelete<TDoc, TCreate, TUpdate>(api: BaseApi<TDoc, TCreate, TUpdate>): BaseApi<TDoc, TCreate, TUpdate> & SoftDeleteMethods<TDoc>;
32
+ declare function withSoftDelete<TApi extends AnyBaseApi>(api: TApi): TApi & SoftDeleteMethods<DocOf<TApi>>;
33
33
  //#endregion
34
34
  export { SoftDeleteMethods, withSoftDelete };
@@ -1,4 +1,4 @@
1
- import { BaseApi, QueryParams, ScopedArgs } from "../api.js";
1
+ import { AnyBaseApi, DocOf, QueryParams, ScopedArgs } from "../api.js";
2
2
  import { PaginatedResult } from "@classytic/repo-core/pagination";
3
3
 
4
4
  //#region src/presets/tree.d.ts
@@ -27,6 +27,6 @@ interface TreeMethods<TDoc> {
27
27
  * const root = await categories.getTree();
28
28
  * const kids = await categories.getChildren({ parentId: 'engineering' });
29
29
  */
30
- declare function withTree<TDoc, TCreate, TUpdate>(api: BaseApi<TDoc, TCreate, TUpdate>): BaseApi<TDoc, TCreate, TUpdate> & TreeMethods<TDoc>;
30
+ declare function withTree<TApi extends AnyBaseApi>(api: TApi): TApi & TreeMethods<DocOf<TApi>>;
31
31
  //#endregion
32
32
  export { TreeMethods, withTree };
@@ -16,14 +16,10 @@
16
16
  function withTree(api) {
17
17
  return Object.assign(api, {
18
18
  async getTree({ token = null, organizationId = null, params = {}, options = {} } = {}) {
19
- const merged = {
20
- ...api.config.defaultParams,
21
- ...params
22
- };
23
19
  return api.request("GET", `${api.baseUrl}/tree`, {
24
20
  token,
25
21
  organizationId,
26
- params: merged,
22
+ params,
27
23
  options
28
24
  });
29
25
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/arc-next",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "description": "React + TanStack Query SDK for Arc resources",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -123,7 +123,8 @@
123
123
  "push": "classytic-push",
124
124
  "release:tag": "node -e \"require('child_process').execSync('npm run push -- v'+require('./package.json').version,{stdio:'inherit'})\"",
125
125
  "release": "npm run push -- main && npm run release:tag && npm publish",
126
- "prepublishOnly": "npm run typecheck && npm test && npm run build"
126
+ "prepublishOnly": "npm run typecheck && npm test && npm run build",
127
+ "typecheck:tests": "tsc --noEmit -p tsconfig.test.json"
127
128
  },
128
129
  "peerDependencies": {
129
130
  "@classytic/repo-core": ">=0.4.0",
@@ -132,10 +133,18 @@
132
133
  "react": ">=19.0.0"
133
134
  },
134
135
  "peerDependenciesMeta": {
135
- "react": { "optional": false },
136
- "@tanstack/react-query": { "optional": false },
137
- "@classytic/repo-core": { "optional": false },
138
- "jose": { "optional": true }
136
+ "react": {
137
+ "optional": false
138
+ },
139
+ "@tanstack/react-query": {
140
+ "optional": false
141
+ },
142
+ "@classytic/repo-core": {
143
+ "optional": false
144
+ },
145
+ "jose": {
146
+ "optional": true
147
+ }
139
148
  },
140
149
  "devDependencies": {
141
150
  "@classytic/dev-tools": "^0.2.0",