@web-ts-toolkit/access-router-client 0.32.0 → 0.34.0

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.
Files changed (7) hide show
  1. package/README.md +258 -14
  2. package/index.d.mts +453 -85
  3. package/index.d.ts +453 -85
  4. package/index.js +1133 -368
  5. package/index.mjs +1133 -368
  6. package/llms.txt +39 -5
  7. package/package.json +11 -4
package/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as axios from 'axios';
2
- import { AxiosInstance, AxiosResponse, AxiosRequestConfig, AxiosHeaders } from 'axios';
2
+ import { AxiosInstance, AxiosResponse, AxiosRequestConfig, InternalAxiosRequestConfig } from 'axios';
3
3
 
4
4
  interface SubQueryOptions {
5
5
  path?: string;
@@ -74,6 +74,7 @@ interface CreateAdvancedOptions {
74
74
  }
75
75
  interface UpdateOptions {
76
76
  returningAll?: boolean;
77
+ includePermissions?: boolean;
77
78
  }
78
79
  interface UpdateAdvancedArgs<TSelect extends Projection = Projection> {
79
80
  select?: TSelect;
@@ -113,35 +114,51 @@ interface DataListArgs {
113
114
  pageSize?: number;
114
115
  }
115
116
  interface DataListOptions {
116
- includePermissions?: boolean;
117
117
  includeCount?: boolean;
118
118
  includeExtraHeaders?: boolean;
119
119
  ignoreCache?: boolean;
120
120
  }
121
121
  interface DataListAdvancedArgs<TSelect extends Projection = Projection> {
122
122
  select?: TSelect;
123
- sort?: Sort;
123
+ sort?: string;
124
124
  skip?: string | number;
125
125
  limit?: string | number;
126
126
  page?: string | number;
127
127
  pageSize?: string | number;
128
128
  }
129
129
  interface DataListAdvancedOptions {
130
- includePermissions?: boolean;
131
130
  includeCount?: boolean;
132
131
  includeExtraHeaders?: boolean;
133
132
  ignoreCache?: boolean;
134
133
  }
135
134
  interface DataReadOptions {
136
- includePermissions?: boolean;
137
135
  ignoreCache?: boolean;
138
136
  }
139
137
  interface DataReadAdvancedArgs<TSelect extends Projection = Projection> {
140
138
  select?: TSelect;
141
- ignoreCache?: boolean;
142
139
  }
140
+ /**
141
+ * Options for `DataService.readAdvanced` and `DataService.readAdvancedFilter`.
142
+ *
143
+ * `ignoreCache` is the documented cache-bypass knob for advanced reads. It
144
+ * lives here — not on `DataReadAdvancedArgs` — so callers use `{ ignoreCache:
145
+ * true }` in the options position to skip an existing cache entry, matching
146
+ * the placement used by the basic `list`, `listAdvanced`, and `read` service
147
+ * methods.
148
+ *
149
+ * `includePermissions` is intentionally absent. The access-router data
150
+ * router body schema for advanced reads (`dataReadByIdBodySchema` and
151
+ * `dataReadFilterBodySchema`) explicitly rejects the `options` key, and the
152
+ * root router drops `item.options` when dispatching data operations
153
+ * server-side (root-router.ts passes `{}` as the options argument to
154
+ * `findById`/`findOne`). Advertising `includePermissions` here was a
155
+ * type-level promise the server cannot honor and the grouped path silently
156
+ * passed through `__query.options.includePermissions` only for the root
157
+ * router to discard it — a direct/grouped asymmetry. The fix removes the
158
+ * dead-letter field from the type and from `__query.options` so direct and
159
+ * grouped advanced reads compose identical payloads.
160
+ */
143
161
  interface DataReadAdvancedOptions {
144
- includePermissions?: boolean;
145
162
  ignoreCache?: boolean;
146
163
  }
147
164
  interface DataDefaults {
@@ -157,67 +174,81 @@ interface AdditionalReqConfig {
157
174
  throwOnError?: boolean;
158
175
  }
159
176
 
177
+ /**
178
+ * Normalized failure payload. Mirrors {@link FailureResult} but kept
179
+ * structurally loose (the {@link Response} discriminated union narrows
180
+ * these fields automatically when consumers branch on `result.success`).
181
+ */
160
182
  interface ResultError {
161
- success: boolean;
183
+ success: false;
162
184
  raw: unknown;
163
- data: unknown;
185
+ data: null;
164
186
  message: string;
165
187
  status: number;
166
188
  headers: Record<string, unknown>;
189
+ totalCount?: number;
167
190
  }
191
+ /**
192
+ * Low-level base class shared by {@link ModelService} and {@link DataService}.
193
+ * Subclassing is supported as an advanced opt-in for callers that need a
194
+ * bespoke service shape: subclasses extend `Service`, build on the shared
195
+ * Axios instance, and reuse the `wrapGet`/`wrapPost`/... paths registered
196
+ * against the adapter's `basePath`. Most callers should use
197
+ * `adapter.createModelService<T>(...)` / `adapter.createDataService<T>(...)`
198
+ * rather than subclassing `Service` directly.
199
+ *
200
+ * The `handleSuccess`/`handleError` helpers normalize Axios responses into
201
+ * the package's {@link Response} discriminated union so direct subclasses
202
+ * produce the same success/failure contract as the built-in services.
203
+ */
168
204
  declare class Service {
169
205
  protected _axios: AxiosInstance;
170
206
  protected _basePath: string;
171
207
  private _wrap;
172
- constructor(axios: AxiosInstance, basePath: string);
208
+ private _throwOnError;
209
+ constructor(axios: AxiosInstance, basePath: string, throwOnError?: boolean);
173
210
  protected handleSuccess(res: AxiosResponse<unknown, unknown>, extra?: {}): Response<unknown>;
174
- protected handleError<T extends ResultError>(error: {
175
- response?: {
176
- status: number;
177
- headers: Record<string, unknown>;
178
- data: unknown;
179
- };
180
- request?: unknown;
181
- message?: string;
182
- }): T;
211
+ protected handleError<T extends Response<unknown, unknown>>(error: unknown): Extract<T, FailureResult>;
212
+ /** Resolves per-call policy against the already-resolved service/adapter default. */
213
+ resolveThrowOnError(override?: boolean): boolean;
183
214
  wrapGet<T = unknown>(url: string, defaultAxiosRequestConfig?: AxiosRequestConfig): (options?: WrapOptions, requestConfig?: AxiosRequestConfig) => Promise<AxiosResponse<T, any, {}>>;
184
215
  wrapPost<T = unknown>(url: string, defaultAxiosRequestConfig?: AxiosRequestConfig): (data?: unknown, options?: WrapOptions, requestConfig?: AxiosRequestConfig) => Promise<AxiosResponse<T, any, {}>>;
185
216
  wrapPut<T = unknown>(url: string, defaultAxiosRequestConfig?: AxiosRequestConfig): (data?: unknown, options?: WrapOptions, requestConfig?: AxiosRequestConfig) => Promise<AxiosResponse<T, any, {}>>;
186
217
  wrapPatch<T = unknown>(url: string, defaultAxiosRequestConfig?: AxiosRequestConfig): (data?: unknown, options?: WrapOptions, requestConfig?: AxiosRequestConfig) => Promise<AxiosResponse<T, any, {}>>;
187
218
  wrapDelete<T = unknown>(url: string, defaultAxiosRequestConfig?: AxiosRequestConfig): (options?: WrapOptions, requestConfig?: AxiosRequestConfig) => Promise<AxiosResponse<T, any, {}>>;
219
+ /**
220
+ * Public bridge to the per-service success/failure callback pipeline and
221
+ * `throwOnError` policy. Adapter-internal grouping machinery calls this so
222
+ * that grouped entries go through the same finalization the direct path
223
+ * uses (`createResponseHandler`). Returns `res` unchanged on success and
224
+ * throws `ServiceError` when both `res.success === false` and the
225
+ * `throwOnError` override (or the service-level default) are enabled.
226
+ */
227
+ applyResponseCallbacks<T extends {
228
+ success: boolean;
229
+ }>(res: T, throwOnErrorOverride?: boolean): T;
230
+ /**
231
+ * Returns a fresh headers object that includes the package-owned
232
+ * `CACHE_HEADER` set to `"true"` (cache eligible) or `"false"` (bypass)
233
+ * according to the `ignoreCache` option. The caller's `CACHE_HEADER`
234
+ * value, if any, wins over the `ignoreCache` default.
235
+ *
236
+ * The input `headers` object is **never mutated**: an `AxiosHeaders`
237
+ * instance is cloned via `.toJSON()` before any value is set, and a
238
+ * plain-object headers input is shallow-copied. Reusing the same
239
+ * caller-owned headers across multiple requests therefore has no
240
+ * hidden side effects, and the order of invocations is irrelevant.
241
+ */
188
242
  updateHeaders(headers: AxiosRequestConfig['headers'], { ignoreCache }: {
189
243
  ignoreCache?: boolean;
190
- }): AxiosHeaders | (Partial<axios.RawAxiosHeaders & {
191
- Accept: axios.AxiosHeaderValue;
192
- "Content-Length": axios.AxiosHeaderValue;
193
- "User-Agent": axios.AxiosHeaderValue;
194
- "Content-Encoding": axios.AxiosHeaderValue;
195
- Authorization: axios.AxiosHeaderValue;
196
- Location: axios.AxiosHeaderValue;
197
- } & {
198
- 'Content-Type': axios.AxiosHeaderValue;
199
- }> & Partial<{
200
- get: AxiosHeaders;
201
- delete: AxiosHeaders;
202
- head: AxiosHeaders;
203
- options: AxiosHeaders;
204
- post: AxiosHeaders;
205
- put: AxiosHeaders;
206
- patch: AxiosHeaders;
207
- purge: AxiosHeaders;
208
- link: AxiosHeaders;
209
- unlink: AxiosHeaders;
210
- query: AxiosHeaders;
211
- } & {
212
- common: AxiosHeaders;
213
- }>);
244
+ }): AxiosRequestConfig['headers'];
214
245
  }
215
246
  declare class ServiceError extends Error {
216
- success: boolean;
217
- raw: unknown;
218
- data: unknown;
219
- status: number;
220
- headers: Record<string, unknown>;
247
+ success: false;
248
+ readonly raw: unknown;
249
+ readonly data: null;
250
+ readonly status: number;
251
+ readonly headers: Record<string, unknown>;
221
252
  constructor(result: ResultError);
222
253
  }
223
254
 
@@ -249,54 +280,54 @@ declare class ModelService<T extends Document> extends Service {
249
280
  constructor({ axios, modelName, basePath, queryPath, mutationPath, onSuccess, onFailure, throwOnError }: Props$1, defaults?: Defaults);
250
281
  list<TData extends Partial<T> = T>(args?: ListArgs, options?: ListOptions, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<ListModelResponse<T, TData>>;
251
282
  listAdvanced<TData extends Partial<T> | never = never, TSelect extends Projection = Projection>(filter: FilterQuery<T>, args?: ListAdvancedArgs<TSelect>, options?: ListAdvancedOptions, axiosRequestConfig?: RequestConfig$1): ModelRequest<ListModelResponse<T, ResolvedSelectedShape<T, TSelect, TData>>>;
252
- create<TData extends Partial<T> = T>(data: object, options?: CreateOptions, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<ModelResponse<T, TData>>;
283
+ create<TData extends Partial<T> = T>(data: object[], options?: CreateOptions, axiosRequestConfig?: RequestConfig$1): ModelRequest<ArrayModelResponse<T, TData>>;
284
+ create<TData extends Partial<T> = T>(data: object, options?: CreateOptions, axiosRequestConfig?: RequestConfig$1): ModelRequest<ModelResponse<T, TData>>;
285
+ createAdvanced<TData extends Partial<T> | never = never, TSelect extends Projection = Projection>(data: object[], args?: CreateAdvancedArgs<TSelect>, options?: CreateAdvancedOptions, axiosRequestConfig?: RequestConfig$1): ModelRequest<ArrayModelResponse<T, ResolvedSelectedShape<T, TSelect, TData>>>;
253
286
  createAdvanced<TData extends Partial<T> | never = never, TSelect extends Projection = Projection>(data: object, args?: CreateAdvancedArgs<TSelect>, options?: CreateAdvancedOptions, axiosRequestConfig?: RequestConfig$1): ModelRequest<ModelResponse<T, ResolvedSelectedShape<T, TSelect, TData>>>;
254
287
  upsert<TData extends Partial<T> = T>(data: object, options?: UpsertOptions, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<ModelResponse<T, TData>>;
255
288
  upsertAdvanced<TData extends Partial<T> | never = never, TSelect extends Projection = Projection>(data: object, args?: UpsertAdvancedArgs<TSelect>, options?: UpsertAdvancedOptions, axiosRequestConfig?: RequestConfig$1): ModelRequest<ModelResponse<T, ResolvedSelectedShape<T, TSelect, TData>>>;
256
- delete(identifier: string, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<Response<string, string>>;
289
+ delete(identifier: string, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<Response<string>>;
257
290
  new<TData extends Partial<T> = T>(axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<ModelResponse<T, TData>>;
258
- distinct(field: string, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<Response<string[], string[]>>;
259
- distinctAdvanced(field: string, conditions: FilterQuery<T>, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<Response<string[], string[]>>;
260
- count(axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<Response<number, number>>;
261
- countAdvanced(filter: FilterQuery<T>, args?: {
262
- access?: 'list' | 'read';
263
- }, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<Response<number, number>>;
291
+ distinct(field: string, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<Response<string[]>>;
292
+ distinctAdvanced(field: string, conditions: FilterQuery<T>, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<Response<string[]>>;
293
+ count(axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<Response<number>>;
294
+ countAdvanced(filter: FilterQuery<T>, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<Response<number>>;
264
295
  read<TData extends Partial<T> = T>(identifier: string, options?: ReadOptions, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<ModelResponse<T, TData>>;
265
296
  readAdvanced<TData extends Partial<T> | never = never, TSelect extends Projection = Projection>(identifier: string, args?: ReadAdvancedArgs<TSelect>, options?: ReadAdvancedOptions, axiosRequestConfig?: RequestConfig$1): ModelRequest<ModelResponse<T, ResolvedSelectedShape<T, TSelect, TData>>>;
266
297
  readAdvancedFilter<TData extends Partial<T> | never = never, TSelect extends Projection = Projection>(filter: FilterQuery<T>, args?: ReadAdvancedArgs<TSelect>, options?: ReadAdvancedOptions, axiosRequestConfig?: RequestConfig$1): ModelRequest<ModelResponse<T, ResolvedSelectedShape<T, TSelect, TData>>>;
267
298
  update<TData extends Partial<T> = T>(identifier: string, data: object, options?: UpdateOptions, axiosRequestConfig?: RequestConfig$1): ModelPromiseMeta & LazyRequest<ModelResponse<T, TData>>;
268
299
  updateAdvanced<TData extends Partial<T> | never = never, TSelect extends Projection = Projection>(identifier: string, data: object, args?: UpdateAdvancedArgs<TSelect>, options?: UpdateAdvancedOptions, axiosRequestConfig?: RequestConfig$1): ModelRequest<ModelResponse<T, ResolvedSelectedShape<T, TSelect, TData>>>;
269
300
  id(id: string): {
270
- subs: <S = T>(field: keyof T) => {
301
+ subs: <S = never, K extends keyof T = keyof T>(field: K) => {
271
302
  list: (axiosRequestConfig?: AxiosRequestConfig<any> & {
272
303
  throwOnError?: boolean;
273
- }) => ModelPromiseMeta & LazyRequest<ListModelResponse<S>>;
274
- listAdvanced: <TData extends Partial<S> = never, TSelect extends readonly string[] = readonly string[]>(filter?: FilterQuery<S>, args?: {
304
+ }) => ModelPromiseMeta & LazyRequest<SubDocumentListResponse<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S>>;
305
+ listAdvanced: <TData extends Partial<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S> = never, TSelect extends readonly string[] = readonly string[]>(filter?: FilterQuery<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S>, args?: {
275
306
  select?: TSelect;
276
307
  }, axiosRequestConfig?: AxiosRequestConfig<any> & {
277
308
  throwOnError?: boolean;
278
- }) => ModelPromiseMeta & LazyRequest<ListModelResponse<S, ResolvedSelectedShape<S, TSelect, TData>>>;
309
+ }) => ModelPromiseMeta & LazyRequest<SubDocumentListResponse<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S, ResolvedSelectedShape<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S, TSelect, TData>>>;
279
310
  read: (subId: string, axiosRequestConfig?: AxiosRequestConfig<any> & {
280
311
  throwOnError?: boolean;
281
- }) => ModelPromiseMeta & LazyRequest<ModelResponse<S>>;
282
- readAdvanced: <TData extends Partial<S> = never, TSelect_1 extends readonly string[] = readonly string[]>(subId: string, args?: {
312
+ }) => ModelPromiseMeta & LazyRequest<SubDocumentResponse<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S>>;
313
+ readAdvanced: <TData extends Partial<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S> = never, TSelect_1 extends readonly string[] = readonly string[]>(subId: string, args?: {
283
314
  select?: TSelect_1;
284
315
  populate?: unknown;
285
316
  }, axiosRequestConfig?: AxiosRequestConfig<any> & {
286
317
  throwOnError?: boolean;
287
- }) => ModelPromiseMeta & LazyRequest<ModelResponse<S, ResolvedSelectedShape<S, TSelect_1, TData>>>;
318
+ }) => ModelPromiseMeta & LazyRequest<SubDocumentResponse<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S, ResolvedSelectedShape<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S, TSelect_1, TData>>>;
288
319
  update: (subId: string, data: object, axiosRequestConfig?: AxiosRequestConfig<any> & {
289
320
  throwOnError?: boolean;
290
- }) => ModelPromiseMeta & LazyRequest<ModelResponse<S>>;
321
+ }) => ModelPromiseMeta & LazyRequest<SubDocumentResponse<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S>>;
291
322
  bulkUpdate: (data: object[], axiosRequestConfig?: AxiosRequestConfig<any> & {
292
323
  throwOnError?: boolean;
293
- }) => ModelPromiseMeta & LazyRequest<ListModelResponse<S>>;
294
- create: (data: object, axiosRequestConfig?: AxiosRequestConfig<any> & {
324
+ }) => ModelPromiseMeta & LazyRequest<SubDocumentListResponse<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S>>;
325
+ create: (data: object | object[], axiosRequestConfig?: AxiosRequestConfig<any> & {
295
326
  throwOnError?: boolean;
296
- }) => ModelPromiseMeta & LazyRequest<ModelResponse<S>>;
327
+ }) => ModelPromiseMeta & LazyRequest<SubDocumentListResponse<[S] extends [never] ? NonNullable<T[K]> extends readonly (infer TItem)[] ? TItem : never : S>>;
297
328
  delete: (subId: string, axiosRequestConfig?: AxiosRequestConfig<any> & {
298
329
  throwOnError?: boolean;
299
- }) => ModelPromiseMeta & LazyRequest<Response<string, string>>;
330
+ }) => ModelPromiseMeta & LazyRequest<Response<string>>;
300
331
  };
301
332
  fetch: (args?: ReadAdvancedArgs, options?: ReadAdvancedOptions, axiosRequestConfig?: RequestConfig$1) => ModelRequest<ModelResponse<T, Partial<T>>>;
302
333
  };
@@ -332,15 +363,109 @@ declare class DataService<T> extends Service {
332
363
  readAdvancedFilter<TData extends Partial<T> | never = never, TSelect extends Projection = Projection>(filter: FilterQuery<T>, args?: DataReadAdvancedArgs<TSelect>, options?: DataReadAdvancedOptions, axiosRequestConfig?: RequestConfig): DataRequest<DataResponse<ResolvedSelectedShape<T, TSelect, TData>>>;
333
364
  }
334
365
 
366
+ /**
367
+ * Thrown by {@link Model.save} when the wrapper cannot determine whether
368
+ * to create or update. This is the "no silent create from a projected
369
+ * read" guarantee (ARC-21): when a read projection omits `_id` AND no
370
+ * persistence identity was captured at read time (the case for
371
+ * `readAdvancedFilter` and other list/filter reads that do not know a
372
+ * single document id), `save()` refuses to POST a new document the
373
+ * caller may not have meant to create. Callers can recover by reading the
374
+ * document with `read(id)` / `readAdvanced(id, ...)` (both capture a
375
+ * persistence identity), or by including `_id` in the projection.
376
+ */
377
+ declare class MissingPersistenceIdentityError extends Error {
378
+ constructor(message: string);
379
+ }
380
+ /**
381
+ * A dirty-tracking wrapper around a model document. Constructed via
382
+ * {@link ModelService.create}, {@link ModelService.read},
383
+ * {@link ModelService.findOne}, or the list methods that return
384
+ * `Model<T>[]`. Property access through the wrapper directly reads/writes
385
+ * the underlying data; `save()` persists only the paths flagged dirty
386
+ * since the last save and merges the server response per the documented
387
+ * concurrency contract.
388
+ *
389
+ * `Model.create<T>(data, service)` is typed as `Model<T, TData> & TData` so
390
+ * callers can read/write fields directly on the wrapper (`user.role =
391
+ * 'owner'`) while still calling `save()`/`reset()`/`isDirty(...)`. The
392
+ * returned wrapper is a fresh snapshot of the post-operation local state;
393
+ * mutating it does not affect sibling wrappers created from the same
394
+ * underlying document.
395
+ *
396
+ * Persistence identity (ARC-21): identity is stored SEPARATELY from the
397
+ * projected document data. When a service reads a single document by id
398
+ * (`read`, `readAdvanced`), it threads an explicit `persistenceId` into
399
+ * `Model.create(...)` so that `save()` resolves the create-vs-update
400
+ * branch from that captured identity, not from `_data._id`. This means a
401
+ * read projection that deliberately omits `_id` (e.g. `select: { name: 1,
402
+ * _id: 0 }`) cannot silently cause a subsequent `save()` to create a
403
+ * duplicate — `save()` updates the same document the wrapper was read
404
+ * from. When neither a `persistenceId` nor an `_id` is present (e.g. an
405
+ * `readAdvancedFilter` projection that strips `_id`), `save()` throws an
406
+ * explicit `MissingPersistenceIdentityError` rather than POSTing a new
407
+ * document the user did not mean to create.
408
+ */
335
409
  declare class Model<T extends Document, TData extends Partial<T> = T> {
336
410
  private _data;
337
411
  private _snapshot;
338
412
  private readonly _service;
339
413
  private modifiedPaths;
340
- constructor(data: TData, adapter: ModelService<T>);
341
- static create<T, TData extends Partial<T> = T>(data: TData, adapter: ModelService<T>): Model<T, TData> & TData;
342
- save(reqConfig?: AxiosRequestConfig): Promise<any>;
414
+ private _persistenceId;
415
+ private readonly _fromExisting;
416
+ constructor(data: TData, adapter: ModelService<T>, persistenceId?: string, fromExisting?: boolean);
417
+ static create<T extends Document, TData extends Partial<T> = T>(data: TData, adapter: ModelService<T>, persistenceId?: string, fromExisting?: boolean): Model<T, TData> & TData;
418
+ /**
419
+ * Persists the currently dirty paths to the server, then merges the
420
+ * server's response back into local state.
421
+ *
422
+ * Concurrency contract:
423
+ *
424
+ * 1. Submitted paths and their values are snapshotted before the request
425
+ * starts, so an in-flight response cannot wipe edits that were made
426
+ * while the request was pending.
427
+ * 2. On success, a submitted path is cleared from `modifiedPaths` only if
428
+ * its current local value still equals the submitted value — i.e. the
429
+ * user has not concurrently re-edited it to a different value.
430
+ * 3. Server-returned values overwrite local values for paths the user did
431
+ * NOT concurrently re-modify during the in-flight save; for paths the
432
+ * user did concurrently re-modify, the local value is preserved and
433
+ * the dirty flag is retained so the concurrent edit is resubmitted on
434
+ * the next `save()`. (Deterministic conflict rule: the newer local
435
+ * edit wins for the same path; the server value becomes its reset
436
+ * baseline without replacing the newer local value.)
437
+ * 4. On failure, no dirty state is cleared and no local value is
438
+ * overwritten; the caller can retry `save()` with the same set.
439
+ * 5. The return value echoes `{ ...result, data }` where `data` is a
440
+ * refreshed `Model` snapshot of the post-save local state (or `null`
441
+ * on failure), matching `ModelResponse<T, TData>`.
442
+ *
443
+ * Persistence identity (ARC-21): create-vs-update is resolved from a
444
+ * captured persistence identity rather than from the projected `_data`
445
+ * payload alone, so a read that strips `_id` (e.g. `select: { name: 1,
446
+ * _id: 0 }`) cannot turn a subsequent `save()` into a silent create of
447
+ * a duplicate. When `_data._id` is present it takes precedence so callers
448
+ * can still deliberately aim `_id` at a bogus id to observe a failing
449
+ * save. When neither `_data._id` nor a captured persistence identity is
450
+ * available (e.g. `readAdvancedFilter` with an `_id`-excluding
451
+ * projection), `save()` throws `MissingPersistenceIdentityError` instead
452
+ * of POSTing a new document.
453
+ */
454
+ save(reqConfig?: AxiosRequestConfig): Promise<ModelResponse<T, TData>>;
343
455
  isDirty(path?: keyof TData | string): boolean;
456
+ /**
457
+ * Marks a path dirty and skips snapshot reconciliation. This is the
458
+ * explicit "include this path on the next save()" escape hatch: even when
459
+ * the effective value still equals the snapshot, the path stays dirty so
460
+ * callers can force a field to be re-sent to the server (e.g., to retrigger
461
+ * server-side defaults or to re-submit a value that another client may
462
+ * have reverted).
463
+ *
464
+ * For implicit writes that reconcile against the snapshot automatically
465
+ * (reverting a field to its baseline clears the dirty flag), use `set()`,
466
+ * `assign(...)`, or direct property assignment — those entry points all
467
+ * run `reconcilePath` after the write.
468
+ */
344
469
  markModified(path: keyof TData | string): this;
345
470
  get<TKey extends keyof TData>(path: TKey): TData[TKey];
346
471
  get(path: string): unknown;
@@ -350,7 +475,6 @@ declare class Model<T extends Document, TData extends Partial<T> = T> {
350
475
  reset(): this;
351
476
  toObject(): TData;
352
477
  toJSON(): TData;
353
- private updateModel;
354
478
  private replaceData;
355
479
  private initializeDirtyState;
356
480
  private prepareData;
@@ -359,12 +483,36 @@ declare class Model<T extends Document, TData extends Partial<T> = T> {
359
483
  private definePublicDataProps;
360
484
  private trackModified;
361
485
  private normalizePath;
486
+ /**
487
+ * Removes `path` from the dirty set when its current top-level value deeply
488
+ * equals the snapshot baseline. Used uniformly by `set()`, `assign()`,
489
+ * public property setters (via the proxy), and `markModified()` so all
490
+ * entry points share the same tracking rule.
491
+ *
492
+ * Note: `_id` is intentionally never reconciled away here — it is excluded
493
+ * from `initializeDirtyState` and managed explicitly during `save()`
494
+ * reconciliation.
495
+ */
496
+ private reconcilePath;
362
497
  }
363
498
 
364
499
  type AnyArray<T> = T[] | ReadonlyArray<T>;
365
500
  type Unpacked<T> = T extends (infer U)[] ? U : T extends ReadonlyArray<infer U> ? U : T;
366
- type ApplyBasicQueryCasting<T> = T | T[] | (T extends (infer U)[] ? U : unknown) | unknown;
367
- type Condition<T> = ApplyBasicQueryCasting<T> | QuerySelector<ApplyBasicQueryCasting<T>>;
501
+ /**
502
+ * Values a known field condition accepts without an operator wrapper.
503
+ *
504
+ * - The scalar value itself (`name: 'Max'`).
505
+ * - An array of scalars — the sibling server expands this to an `$in` query.
506
+ * - For array-typed document fields, the element type is also accepted as a
507
+ * bare condition (e.g. `tags: 'vip'` matches any array containing `'vip'`).
508
+ * - RegExp is only accepted where `T` is (or unwraps to) `string`.
509
+ *
510
+ * The naked `unknown` that previously terminated this union is gone. Use
511
+ * `ServerSideCast<T>` / `DottedPathFilter<T>` for the cases that needed it
512
+ * (dynamic dotted paths and explicit server-side casting).
513
+ */
514
+ type ApplyBasicQueryCasting<T> = T | T[] | (T extends AnyArray<unknown> ? Unpacked<T> : never) | (T extends string ? RegExp : never);
515
+ type Condition<T> = ApplyBasicQueryCasting<T> | QuerySelector<ApplyBasicQueryCasting<T>> | LazyRequest<unknown>;
368
516
  type _FilterQuery<T> = {
369
517
  [P in keyof T]?: Condition<T[P]>;
370
518
  } & RootQuerySelector<T>;
@@ -386,7 +534,6 @@ type RootQuerySelector<T> = {
386
534
  $where?: string | ((...args: never[]) => unknown);
387
535
  /** @see https://www.mongodb.com/docs/manual/reference/operator/query/comment/#op._S_comment */
388
536
  $comment?: string;
389
- [key: string]: unknown;
390
537
  };
391
538
  type QuerySelector<T> = {
392
539
  $eq?: T;
@@ -410,11 +557,56 @@ type QuerySelector<T> = {
410
557
  $regex?: T extends string ? RegExp | string : never;
411
558
  $options?: T extends string ? string : never;
412
559
  };
560
+ /**
561
+ * Escape hatch for dynamic dotted paths and explicit server-side casting.
562
+ *
563
+ * `DottedPathFilter<T>` restores schema-less field matching: every
564
+ * `Record<string, unknown>` value is forwarded to the sibling server
565
+ * untouched, so dotted paths such as `'user.friends.name'` and values cast
566
+ * on the server side still typecheck.
567
+ *
568
+ * Crucially, `DottedPathFilter<T>` restores this looseness only when the
569
+ * caller explicitly asks for it; it does NOT weaken the typed
570
+ * `FilterQuery<T>` surface, so a stray invalid value on a known field still
571
+ * fails to compile.
572
+ */
573
+ type DottedPathFilter<T> = _FilterQuery<T> & {
574
+ [key: string]: unknown;
575
+ };
576
+ /**
577
+ * Escape hatch for explicit server-side casting. Use this at the call site
578
+ * of any typed `FilterQuery<T>` parameter when you need to forward a value
579
+ * the client type cannot express (server-side casting, aggregation-shaped
580
+ * values for `$expr`, or a dotted-path condition that the typed surface does
581
+ * not model). The sibling server accepts arbitrary objects/arrays for
582
+ * filters (`objectOrArraySchema`), so this never causes a runtime failure;
583
+ * it is purely a deliberate compile-time opt-out.
584
+ */
585
+ type ServerSideCast<T> = DottedPathFilter<T>;
413
586
 
414
587
  /**
415
588
  * Wraps a lazy promise function with optional metadata.
416
- * The promise is only created when `.then()`, `.catch()`, `.finally()`, or `.exec()` is called.
417
- * Metadata properties are merged onto the returned object via `Object.assign`.
589
+ *
590
+ * The promise is only created when `.then()`, `.catch()`, `.finally()`, or
591
+ * `.exec()` is called, and a single underlying promise is shared across all
592
+ * of those entry points so repeated chaining attaches to the same execution
593
+ * rather than re-invoking the executor.
594
+ *
595
+ * Behavior notes:
596
+ *
597
+ * - **Sync executor failures become rejections.** The executor is invoked
598
+ * through `Promise.resolve().then(execute)`, so a synchronous throw from
599
+ * `execute` is converted to a rejected promise and reaches `.catch()`
600
+ * and `await` as a rejection rather than escaping synchronously.
601
+ * - **Metadata is private.** Each meta entry is installed with
602
+ * `Object.defineProperty(..., { enumerable: false, writable: false,
603
+ * configurable: false })` so consumers cannot accidentally iterate,
604
+ * serialize, or reassign it. Direct property reads (`prom.__query`) still
605
+ * work for adapter-internal machinery (e.g. `adapter.group(...)`).
606
+ * - **One execution.** The first call to `exec()`, `.then()`,
607
+ * `.catch()`, or `.finally()` caches the underlying promise and stamps
608
+ * the wrapper with `STARTED_KEY = true`. Subsequent calls reuse the same
609
+ * promise and never re-invoke the executor.
418
610
  */
419
611
  declare const wrapLazyPromise: <T, M = undefined>(promiseFn: () => Promise<T>, meta?: M) => M & LazyRequest<T>;
420
612
 
@@ -435,6 +627,7 @@ type Sort = string | {
435
627
  [key: string]: SortOrder;
436
628
  } | [string, SortOrder][] | undefined | null;
437
629
  type FilterQuery<T> = _FilterQuery<T>;
630
+
438
631
  interface Include {
439
632
  model: string;
440
633
  op: 'list' | 'read' | 'count';
@@ -455,19 +648,79 @@ interface Populate {
455
648
  interface Document {
456
649
  _id?: string;
457
650
  }
458
- interface Response<T1, T2 = T1> {
459
- success: boolean;
651
+ /**
652
+ * Successful response. `raw` and `data` are non-null and `success` is
653
+ * narrowed to `true` so `if (result.success)` exposes the documented
654
+ * payload shape. `message` is initialized for symmetry with failures but
655
+ * may be the empty string when the server omits a message on success.
656
+ */
657
+ interface SuccessResult<T1, T2 = T1> {
658
+ success: true;
460
659
  raw: T1;
461
660
  data: T2;
462
661
  message: string;
463
662
  status: number;
464
663
  headers: Record<string, string>;
465
664
  }
466
- type ModelResponse<T, TData extends Partial<T> = T> = Response<TData, Model<T, TData> & TData>;
467
- type ArrayModelResponse<T, TData extends Partial<T> = T> = Response<TData[], (Model<T, TData> & TData)[]>;
468
- type ListModelResponse<T, TData extends Partial<T> = T> = ArrayModelResponse<T, TData> & {
665
+ /**
666
+ * Failure response. `raw` carries the server error payload (or `null`
667
+ * when no response body was received, e.g. a network error). `data` is
668
+ * always `null` on failure. `message` is populated from the structured
669
+ * problem payload when possible; `status` is the failing HTTP status
670
+ * (or `0` when no response was received).
671
+ */
672
+ interface FailureResult<TError = unknown> {
673
+ success: false;
674
+ raw: TError | null;
675
+ data: null;
676
+ message: string;
677
+ status: number;
678
+ headers: Record<string, string>;
679
+ }
680
+ /**
681
+ * Discriminated response union. Branch on `result.success` to narrow
682
+ * `raw`/`data` to their successful shapes or to the documented error
683
+ * payload.
684
+ *
685
+ * `T1` is the successful `raw` payload type; `T2` is the successful `data`
686
+ * payload type (after client wrapping, e.g. `Model<T>`). `TError` is the
687
+ * optional server error payload type and defaults to `unknown`. On failure,
688
+ * `data` is `null` and `raw` is `TError | null`, never the success payload
689
+ * type unless a caller explicitly chooses that error type.
690
+ */
691
+ type Response<T1, T2 = T1, TError = unknown> = SuccessResult<T1, T2> | FailureResult<TError>;
692
+ type ModelResponse<T extends Document, TData extends Partial<T> = T> = Response<TData, Model<T, TData> & TData>;
693
+ type ArrayModelResponse<T extends Document, TData extends Partial<T> = T> = Response<TData[], (Model<T, TData> & TData)[]>;
694
+ /**
695
+ * `ListModelResponse` always carries `totalCount` on both branches. The field
696
+ * defaults to `0` at runtime on failure or when the server did not emit count
697
+ * metadata (`includeCount: false`), so callers that read it without narrowing
698
+ * see a deterministic number rather than `undefined`.
699
+ */
700
+ type ListModelResponse<T extends Document, TData extends Partial<T> = T> = ArrayModelResponse<T, TData> & {
469
701
  totalCount: number;
470
702
  };
703
+ /**
704
+ * Subdocument responses deliberately do NOT wrap `data` in `Model<S>`.
705
+ * Returning a save-capable `Model<S>` here was unsafe because `Model.save()`
706
+ * would target the parent route with the subdocument `_id` instead of
707
+ * `/:parentId/:sub/:subId`. Subdocument callers that need persistence must
708
+ * call `subService.update(subId, data)` (or `create`/`bulkUpdate`) explicitly
709
+ * with the parent-scoped helper returned by `id(parentId).subs(field)`.
710
+ *
711
+ * `SubDocumentResponse` is the single-document shape; `data` is the plain
712
+ * subdocument payload or `null` on failure.
713
+ */
714
+ type SubDocumentResponse<S, TData extends Partial<S> = S> = Response<TData, TData>;
715
+ /**
716
+ * Subdocument list/array responses. `data` is the plain array of subdocument
717
+ * payloads (no `Model` wrapping) and `raw` is the server's original array
718
+ * payload. `count` mirrors the server's `count` field (the length of the
719
+ * returned array); the sibling server never emits a `totalCount` here.
720
+ */
721
+ type SubDocumentListResponse<S, TData extends Partial<S> = S> = Response<TData[], TData[]> & {
722
+ count: number;
723
+ };
471
724
  interface Task {
472
725
  type: string;
473
726
  args: unknown;
@@ -478,7 +731,15 @@ type RootDataOperation = 'list' | 'read';
478
731
  interface RootModelQueryMeta {
479
732
  target: 'model';
480
733
  name: string;
481
- model: string;
734
+ /**
735
+ * Carries the model name when this entry is consumed as a sub-query
736
+ * source: the sibling server reads `model` from a `$$sq` payload to
737
+ * resolve the target model service. Top-level root entries omit `model`
738
+ * (the sibling `RootQueryEntry` schema uses `name`); the server schema
739
+ * permits extra fields via `.passthrough()`, so a stray `model` is
740
+ * harmless there.
741
+ */
742
+ model?: string;
482
743
  op: RootModelOperation;
483
744
  id?: string;
484
745
  sub?: string;
@@ -505,6 +766,7 @@ interface RootDataQueryMeta {
505
766
  type RootQueryMeta = RootModelQueryMeta | RootDataQueryMeta;
506
767
  interface ModelPromiseMeta {
507
768
  __op: string;
769
+ __throwOnError?: boolean;
508
770
  __query: RootModelQueryMeta;
509
771
  __requestConfig?: AxiosRequestConfig;
510
772
  __service?: ModelService<Document>;
@@ -520,6 +782,7 @@ type ListDataResponse<T> = ArrayDataResponse<T> & {
520
782
  };
521
783
  interface DataPromiseMeta {
522
784
  __op: string;
785
+ __throwOnError?: boolean;
523
786
  __query: RootDataQueryMeta;
524
787
  __requestConfig?: AxiosRequestConfig;
525
788
  __service?: DataService<unknown>;
@@ -532,15 +795,86 @@ interface WrapOptions {
532
795
  pathParams?: Record<string, string | number>;
533
796
  }
534
797
 
798
+ /**
799
+ * Adapter-scoped cache control surface returned by `useCacheInterceptors`.
800
+ * The adapter delegates `clearCache()` to {@link clear} on credential
801
+ * transitions (login/logout/token refresh/tenant change) and
802
+ * `disposeCache()` to {@link dispose} when the adapter is torn down to
803
+ * release cache timers so they do not keep a Node process alive.
804
+ */
805
+ interface CacheController {
806
+ clear(): void;
807
+ dispose(): void;
808
+ }
809
+ /**
810
+ * Resolves a stable, non-secret identity partition token for a credentialed
811
+ * request. Requests that share a token share cache entries; requests with
812
+ * different tokens never do. Returning `undefined` bypasses the cache for that
813
+ * credentialed request, so credentials cannot be reused across identities.
814
+ *
815
+ * The token is mixed into the cache key alongside the URL and request body. Do
816
+ * not return raw cookies, authorization values, or other secrets; sensitive
817
+ * auth headers are excluded from cache keys regardless of the returned token.
818
+ */
819
+ type CachePartitioner = (config: InternalAxiosRequestConfig) => string | undefined;
820
+
821
+ /**
822
+ * Options for {@link createAdapter}. `rootRouterPath` is the single-segment
823
+ * path used by `adapter.group(...)` for batched root requests
824
+ * (defaults to `'root'`). Per-adapter `onSuccess`/`onFailure`/`throwOnError`
825
+ * apply to every service created by this adapter and are overridden by
826
+ * per-service options on {@link ModelServiceOptions} and
827
+ * {@link DataServiceOptions}.
828
+ *
829
+ * Cache controls (only in effect when `cacheTTL > 0`):
830
+ *
831
+ * - `cacheTTL` — seconds a cached GET response is reused before revalidation.
832
+ * - `cachePartition` — required to cache credentialed requests safely (see
833
+ * {@link CachePartitioner}); credentialed requests without a stable,
834
+ * non-secret partition token bypass the cache so one identity cannot
835
+ * receive a response created under another.
836
+ * - `cacheCapacity` — bounds the number of cached entries; defaults to 100 and
837
+ * evicts the LRU entry when the limit is exceeded.
838
+ *
839
+ * Use the returned adapter's `clearCache()` on credential transitions
840
+ * (login/logout/token refresh/tenant change) and `disposeCache()` when the
841
+ * adapter is no longer needed to release cache timers.
842
+ */
535
843
  interface AdapterOptions {
536
844
  rootRouterPath?: string;
537
845
  onSuccess?: ResponseCallback;
538
846
  onFailure?: ResponseCallback;
539
847
  throwOnError?: boolean;
540
848
  cacheTTL?: number;
849
+ /**
850
+ * Partition strategy for credentialed cache entries. When the adapter is
851
+ * credentialed (which is the default), caching is only enabled for requests
852
+ * whose `cachePartition` returns a stable, non-secret identity token. Requests
853
+ * without a partition key bypass the cache so that one identity can never
854
+ * receive a response created under another identity.
855
+ *
856
+ * The returned value must be a stable, non-secret token (for example a user
857
+ * id or tenant id). Never return raw cookies, authorization values, or other
858
+ * secrets; those headers are excluded from cache keys regardless.
859
+ */
860
+ cachePartition?: CachePartitioner;
861
+ /**
862
+ * Maximum number of cached entries retained per adapter. Defaults to 100.
863
+ */
864
+ cacheCapacity?: number;
541
865
  modelDefaults?: Defaults;
542
866
  dataDefaults?: DataDefaults;
543
867
  }
868
+ /**
869
+ * Options for {@link createAdapter}.createModelService<T>. Mirrors the
870
+ * server-side `access-router` model route configuration: `modelName` is the
871
+ * server-registered model name, `basePath` is the URL segment relative to
872
+ * the adapter `baseURL` (e.g. `'users'` resolves to `${baseURL}/users`),
873
+ * `queryPath` defaults to `'__query'` and `mutationPath` defaults to
874
+ * `'__mutation'` — match these to the server's `queryRouteSegment` and
875
+ * mutation route configuration. Per-service `onSuccess`/`onFailure`/
876
+ * `throwOnError` override the adapter-level defaults.
877
+ */
544
878
  interface ModelServiceOptions {
545
879
  modelName: string;
546
880
  basePath: string;
@@ -550,6 +884,14 @@ interface ModelServiceOptions {
550
884
  onFailure?: ResponseCallback;
551
885
  throwOnError?: boolean;
552
886
  }
887
+ /**
888
+ * Options for {@link createAdapter}.createDataService<T>. Mirrors the
889
+ * server-side `access-router` data route configuration: `dataName` is the
890
+ * server-registered data name, `basePath` is the URL segment relative to
891
+ * the adapter `baseURL`, `queryPath` defaults to `'__query'`. Per-service
892
+ * `onSuccess`/`onFailure`/`throwOnError` override the adapter-level
893
+ * defaults.
894
+ */
553
895
  interface DataServiceOptions {
554
896
  dataName: string;
555
897
  basePath: string;
@@ -561,13 +903,39 @@ interface DataServiceOptions {
561
903
  /**
562
904
  * Creates a typed API adapter for `@web-ts-toolkit/access-router` model and data routes.
563
905
  *
906
+ * The adapter owns its own Axios instance, optional request cache, and
907
+ * per-adapter identity token (used by {@link group} to reject requests
908
+ * owned by a different adapter before any network activity). The returned
909
+ * adapter is frozen and exposes:
910
+ *
911
+ * - `axios` — the underlying Axios instance for advanced configuration or
912
+ * attaching interceptors (the package's cache interceptors are installed
913
+ * when `cacheTTL > 0`).
914
+ * - `createModelService<T>(...)` / `createDataService<T>(...)` — typed
915
+ * factories for the model and data route clients.
916
+ * - `clearCache()` / `disposeCache()` — adapter-scoped cache controls
917
+ * installed by {@link AdapterOptions.cacheTTL}. `clearCache()` drops all
918
+ * cached entries (call on login/logout/token refresh/tenant switch);
919
+ * `disposeCache()` also releases the cache's timers so a long-lived
920
+ * adapter can be torn down cleanly.
921
+ * - `wrapGet` / `wrapPost` / `wrapPut` / `wrapPatch` / `wrapDelete` —
922
+ * low-level helpers that wrap a raw Axios call to a single path segment
923
+ * with `pathParams`/`queryParams` templating and the package's
924
+ * normalized success/failure handling.
925
+ * - `group(...)` — batches multiple lazy requests created by this
926
+ * adapter's services into one root round trip. Rejected before network
927
+ * activity if any input has already started execution or was created by
928
+ * a different adapter.
929
+ *
564
930
  * @example
565
931
  * const adapter = createAdapter({ baseURL: 'http://localhost:3000/api' });
566
932
  * const userService = adapter.createModelService<User>({ modelName: 'User', basePath: 'users' });
567
933
  */
568
934
  declare function createAdapter(axiosConfig?: AxiosRequestConfig, adapterOptions?: AdapterOptions): Readonly<{
569
935
  axios: axios.AxiosInstance;
570
- createModelService: <T>({ modelName, basePath, queryPath, mutationPath, onSuccess, onFailure, throwOnError, }: ModelServiceOptions, defaults?: Defaults) => ModelService<T>;
936
+ clearCache: () => void;
937
+ disposeCache: () => void;
938
+ createModelService: <T extends Document>({ modelName, basePath, queryPath, mutationPath, onSuccess, onFailure, throwOnError, }: ModelServiceOptions, defaults?: Defaults) => ModelService<T>;
571
939
  createDataService: <T>({ dataName, basePath, queryPath, onSuccess, onFailure, throwOnError }: DataServiceOptions, defaults?: DataDefaults) => DataService<T>;
572
940
  wrapGet: <T = unknown>(url: string, defaultConfig?: AxiosRequestConfig) => (options?: WrapOptions, requestConfig?: AxiosRequestConfig) => Promise<axios.AxiosResponse<T, any, {}>>;
573
941
  wrapPost: <T = unknown>(url: string, defaultConfig?: AxiosRequestConfig) => (data?: unknown, options?: WrapOptions, requestConfig?: AxiosRequestConfig) => Promise<axios.AxiosResponse<T, any, {}>>;
@@ -596,4 +964,4 @@ declare function removeItemById<T extends {
596
964
  _id: string;
597
965
  }>(items: T[], targetItem: T): T[];
598
966
 
599
- export { type AdditionalReqConfig, type ArrayDataResponse, type ArrayModelResponse, type CreateAdvancedArgs, type CreateAdvancedOptions, type CreateOptions, CustomHeaders, type DataDefaults, type DataListAdvancedArgs, type DataListAdvancedOptions, type DataListArgs, type DataListOptions, type DataPromiseMeta, type DataReadAdvancedArgs, type DataReadAdvancedOptions, type DataReadOptions, type DataRequest, type DataResponse, DataService, type Defaults, type Document, type FilterQuery, type Include, type KeyValueProjection, type LazyRequest, type ListAdvancedArgs, type ListAdvancedOptions, type ListArgs, type ListDataResponse, type ListModelResponse, type ListOptions, Model, type ModelPromiseMeta, type ModelRequest, type ModelResponse, ModelService, type Populate, type PopulateAccess, type Projection, type ReadAdvancedArgs, type ReadAdvancedOptions, type ReadOptions, type ResolvedSelectedShape, type Response, type ResponseCallback, type ResultError, type RootDataQueryMeta, type RootModelQueryMeta, type RootQueryMeta, type SelectedKeys, type SelectedShape, Service, ServiceError, type Sort, type SortOrder, type SubQueryOptions, type Task, type UpdateAdvancedArgs, type UpdateAdvancedOptions, type UpdateOptions, type UpsertAdvancedArgs, type UpsertAdvancedOptions, type UpsertOptions, type WrapOptions, createAdapter, removeItemById, replaceItemById, wrapLazyPromise };
967
+ export { type AdapterOptions, type AdditionalReqConfig, type ArrayDataResponse, type ArrayModelResponse, type CacheController, type CachePartitioner, type CreateAdvancedArgs, type CreateAdvancedOptions, type CreateOptions, CustomHeaders, type DataDefaults, type DataListAdvancedArgs, type DataListAdvancedOptions, type DataListArgs, type DataListOptions, type DataPromiseMeta, type DataReadAdvancedArgs, type DataReadAdvancedOptions, type DataReadOptions, type DataRequest, type DataResponse, DataService, type DataServiceOptions, type Defaults, type Document, type DottedPathFilter, type FailureResult, type FilterQuery, type Include, type KeyValueProjection, type LazyRequest, type ListAdvancedArgs, type ListAdvancedOptions, type ListArgs, type ListDataResponse, type ListModelResponse, type ListOptions, MissingPersistenceIdentityError, Model, type ModelPromiseMeta, type ModelRequest, type ModelResponse, ModelService, type ModelServiceOptions, type Populate, type PopulateAccess, type Projection, type ReadAdvancedArgs, type ReadAdvancedOptions, type ReadOptions, type ResolvedSelectedShape, type Response, type ResponseCallback, type ResultError, type RootDataQueryMeta, type RootModelQueryMeta, type RootQueryMeta, type SelectedKeys, type SelectedShape, type ServerSideCast, Service, ServiceError, type Sort, type SortOrder, type SubDocumentListResponse, type SubDocumentResponse, type SubQueryOptions, type SuccessResult, type Task, type UpdateAdvancedArgs, type UpdateAdvancedOptions, type UpdateOptions, type UpsertAdvancedArgs, type UpsertAdvancedOptions, type UpsertOptions, type WrapOptions, createAdapter, removeItemById, replaceItemById, wrapLazyPromise };