# @data-client/rest

## 0.17.0

### Minor Changes

- [#3914](https://github.com/reactive/data-client/pull/3914) [`930c8ed`](https://github.com/reactive/data-client/commit/930c8ed04b6f9fcb2d131f39cc706a5eeb0edc4d) - resource() accepts [nonFilterArgumentKeys](https://dataclient.io/rest/api/Collection#nonfilterargumentkeys)

  ```ts
  const PostResource = resource({
    path: '/:group/posts/:id',
    searchParams: {} as { orderBy?: string; author?: string },
    schema: Post,
    nonFilterArgumentKeys: ['orderBy'],
  });
  ```

## 0.16.6

### Patch Changes

- [#3868](https://github.com/reactive/data-client/pull/3868) [`8a7c8d9`](https://github.com/reactive/data-client/commit/8a7c8d9cc4228a6281849f56121699f237af4b0f) - Add `content` property to RestEndpoint for typed response parsing

  Set `content` to control how the response body is parsed, with automatic return type inference:

  ```ts
  const downloadFile = new RestEndpoint({
    path: '/files/:id/download',
    content: 'blob',
    dataExpiryLength: 0,
  });
  const blob: Blob = await ctrl.fetch(downloadFile, { id: '123' });
  ```

  Accepted values: `'json'`, `'blob'`, `'text'`, `'arrayBuffer'`, `'stream'`.

  Non-JSON content types (`'blob'`, `'text'`, `'arrayBuffer'`, `'stream'`) constrain `schema` to
  `undefined` at the type level, with a runtime check that throws if a normalizable schema is set.

  When `content` is not set, auto-detection now handles binary Content-Types (`image/*`,
  `application/octet-stream`, `application/pdf`, etc.) by returning `response.blob()` instead of
  corrupting data via `.text()`.

- [#3904](https://github.com/reactive/data-client/pull/3904) [`8af3d5e`](https://github.com/reactive/data-client/commit/8af3d5ee3dbbb637805e99cbd01801d3587bedbd) - Export `CollectionOptions` from the public `@data-client/endpoint` and `@data-client/rest` entrypoints.

- [#3910](https://github.com/reactive/data-client/pull/3910) [`81c63a0`](https://github.com/reactive/data-client/commit/81c63a00c668d805b6b8d0d9efdf2aacb5d32253) - Fix [Collection](https://dataclient.io/rest/api/Collection) extender body types to match their HTTP method semantics

  PATCH extenders (`.move`, `.remove`) now type their body as `Partial`, matching
  [`partialUpdate`](https://dataclient.io/rest/api/resource#partialupdate). Previously they
  required the full body type even though they are PATCH endpoints.

  Standalone `RestEndpoint` without an explicit `body` option now derives a typed
  body from the Collection's entity schema instead of falling back to `any`.

  ```ts
  const MyResource = resource({
    path: '/articles/:id',
    schema: Article,
    body: {} as { title: string; content: string },
  });

  // move (PATCH) now accepts partial body
  MyResource.getList.move({ id: '1' }, { title: 'new title' });

  // push (POST) still requires full body
  MyResource.getList.push({ title: 'hi', content: 'there' });
  ```

- Updated dependencies [[`8af3d5e`](https://github.com/reactive/data-client/commit/8af3d5ee3dbbb637805e99cbd01801d3587bedbd)]:
  - @data-client/endpoint@0.16.6

## 0.16.5

### Patch Changes

- [#3866](https://github.com/reactive/data-client/pull/3866) [`16f5d92`](https://github.com/reactive/data-client/commit/16f5d92598de05e92b88af98a9d63eecf27ab819) - Bundle `path-to-regexp` as tree-shaken ESM

  Bundle only the functions we use (`compile`, `parse`, `pathToRegexp`) from
  `path-to-regexp` into the ESM/browser build via rollup. This eliminates
  the CJS/ESM boundary that broke StackBlitz WebContainers and reduces bundle
  size by tree-shaking unused exports (`match`, `stringify`, and the `ID` regex).

## 0.16.4

### Patch Changes

- [#3862](https://github.com/reactive/data-client/pull/3862) [`a214720`](https://github.com/reactive/data-client/commit/a214720fd12e1360d00e194b389aa82aff6b91fd) - Fix StackBlitz WebContainers compatibility with path-to-regexp

  Use namespace import (`import *`) instead of named imports for the CJS
  `path-to-regexp` dependency. Named imports trigger webpack's per-export
  presence validation, which fails in StackBlitz's WebContainers environment.
  Namespace imports defer property access to runtime, bypassing the check
  with no tree-shaking loss.

## 0.16.3

### Patch Changes

- [#3858](https://github.com/reactive/data-client/pull/3858) [`c83a81d`](https://github.com/reactive/data-client/commit/c83a81d4183b4b0f7c3a41f5b49fdba890406a6b) - Fix `maxEntityDepth` missing from Entity types on TypeScript 4.0

  `maxEntityDepth` was not included in the TS 4.0 legacy type definitions,
  so TypeScript 4.0 users could not set or reference this property on Entity classes.

- [#3860](https://github.com/reactive/data-client/pull/3860) [`886f2cf`](https://github.com/reactive/data-client/commit/886f2cf9032d5bb929b4bab63d61dc34398ca539) - Fix compatibility with StackBlitz WebContainers

  Consolidate `path-to-regexp` imports into a single module to avoid
  CJS/ESM interop failures in StackBlitz's WebContainers environment,
  where webpack could not resolve the `pathToRegexp` named export from
  the CJS `path-to-regexp` package.

  Also caches `pathToRegexp()` results, improving repeated `testKey()` performance.

- Updated dependencies [[`c83a81d`](https://github.com/reactive/data-client/commit/c83a81d4183b4b0f7c3a41f5b49fdba890406a6b)]:
  - @data-client/endpoint@0.16.3

## 0.16.2

### Patch Changes

- [#3847](https://github.com/reactive/data-client/pull/3847) [`e93e820`](https://github.com/reactive/data-client/commit/e93e820a112683badd4020c7c04c2284a0f6d8bf) - Fix TypeScript for `RestEndpoint` subclasses when the path is inferred as `string`

  If you extend `RestEndpoint` with a generic such as `O extends RestGenerics = any`, TypeScript can widen a path literal to `string`. Constructor callbacks like `getOptimisticResponse`, `key`, `url`, and `process` could then get the wrong parameter types (or unusable unions), even though calling the endpoint still worked at runtime.

  The same problem could show up when you set `searchParams: undefined` explicitly next to a `body` and a widened path. Both cases now type-check as you would expect.

  ```typescript
  import { Entity } from '@data-client/endpoint';
  import { RestEndpoint, RestGenerics } from '@data-client/rest';

  class Item extends Entity {
    readonly id = '';
  }

  class AppRestEndpoint<O extends RestGenerics = any> extends RestEndpoint<O> {}

  new AppRestEndpoint({
    path: '/items' as string,
    schema: Item,
    body: {} as { name: string },
    getOptimisticResponse(_snap, body) {
      body.name;
      return body;
    },
  });

  new AppRestEndpoint({
    path: '/search' as string,
    searchParams: undefined,
    schema: Item,
    body: {} as { q: string },
    getOptimisticResponse(_snap, body) {
      body.q;
      return body;
    },
  });
  ```

## 0.16.1

### Patch Changes

- [#3845](https://github.com/reactive/data-client/pull/3845) [`14095fe`](https://github.com/reactive/data-client/commit/14095fe768625cf11ce3d80d3493571029cf5b67) - Fix type errors when using concrete body types with subclassed RestEndpoint

  Subclassing RestEndpoint (the standard pattern for adding auth headers, custom
  serialization, etc.) could produce type errors when specifying concrete body types.

  ```ts
  // Before: type error on body ❌
  class AuthdEndpoint<O extends RestGenerics = any> extends RestEndpoint<O> {}
  new AuthdEndpoint({
    method: 'PUT',
    path: '/users/:id',
    body: {} as { username: string; email: string },
  });

  // After: works correctly ✓
  ```

## 0.16.0

### Minor Changes

- [#3829](https://github.com/reactive/data-client/pull/3829) [`63633c7`](https://github.com/reactive/data-client/commit/63633c714b5c041e04891255683e5a899c3d3f22) - Add [schema.Lazy](https://dataclient.io/rest/api/Lazy) for deferred relationship denormalization.

  `schema.Lazy` wraps a relationship field so denormalization returns raw primary keys
  instead of resolved entities. Use `.query` with [useQuery](/docs/api/useQuery) to
  resolve on demand in a separate memo/GC scope.

  New exports: `schema.Lazy`, `Lazy`

  ```ts
  class Department extends Entity {
    buildings: string[] = [];
    static schema = {
      buildings: new schema.Lazy([Building]),
    };
  }

  // dept.buildings = ['bldg-1', 'bldg-2'] (raw PKs)
  const buildings = useQuery(Department.schema.buildings.query, dept.buildings);
  ```

- [#3783](https://github.com/reactive/data-client/pull/3783) [`1f34136`](https://github.com/reactive/data-client/commit/1f34136f1d0902ee5456089f2d2f9f35c9f4a758) - Add `Collection.moveWith()` for custom move schemas

  Analogous to [`addWith()`](https://dataclient.io/rest/api/Collection#addWith), `moveWith()` constructs a custom move schema that controls how entities are added to their destination collection. The remove behavior is automatically derived from the collection type (Array or Values).

  New exports: `unshift` merge function for convenience.

  ```ts
  import { Collection, unshift } from '@data-client/rest';

  class MyCollection extends Collection {
    constructor(schema, options) {
      super(schema, options);
      this.move = this.moveWith(unshift);
    }
  }
  ```

- [#3757](https://github.com/reactive/data-client/pull/3757) [`02555a2`](https://github.com/reactive/data-client/commit/02555a23ef11c0a6c829d795067b634c0594fe14) - RestEndpoint.path and Resource.path syntax updated

  Upgrading path-to-regexp from 6 to 8.
  - https://github.com/pillarjs/path-to-regexp/releases/tag/v8.0.0
  - https://github.com/pillarjs/path-to-regexp/releases/tag/v7.0.0

  BREAKING CHANGES:
  - /:optional? -> {/:optional}
  - /:repeating+ -> /\*repeating (typed as string[])
  - /:repeating* -> {/*repeating} (typed as string[])
  - /:id(\d+) -> /:id (custom regex removed)
  - /:with-dash -> /:"with-dash"
  - `(`, `)`, `[`, `]`, `+`, `?`, `!` must be escaped `"\\("`
    - `{}()[]+?!:*\` are all characters that need escaping

  Migrate using:
  `npx skills add https://github.com/reactive/data-client --skill path-to-regexp-v8-migration`

### Patch Changes

- [#3782](https://github.com/reactive/data-client/pull/3782) [`3b85c82`](https://github.com/reactive/data-client/commit/3b85c820f8046a056d9180ff5d2fe1a883b6998c) - Fix `searchParams: undefined` being widened to `any` in TypeScript 6 non-strict mode

  TypeScript 6.0 widens `undefined` to `any` during generic inference when `strictNullChecks` is off.
  This caused `RestEndpoint` with `searchParams: undefined` to incorrectly accept arbitrary arguments.

- [#3757](https://github.com/reactive/data-client/pull/3757) [`02555a2`](https://github.com/reactive/data-client/commit/02555a23ef11c0a6c829d795067b634c0594fe14) - Fix `undefined` optional path params being interpolated as literal `"undefined"` in URLs

- Updated dependencies [[`63633c7`](https://github.com/reactive/data-client/commit/63633c714b5c041e04891255683e5a899c3d3f22), [`1f34136`](https://github.com/reactive/data-client/commit/1f34136f1d0902ee5456089f2d2f9f35c9f4a758), [`869f28f`](https://github.com/reactive/data-client/commit/869f28fc651ca5e8b0f935089fc0b8d8ce8585cb)]:
  - @data-client/endpoint@0.16.0

## 0.15.7

### Patch Changes

- [#3738](https://github.com/reactive/data-client/pull/3738) [`4425a37`](https://github.com/reactive/data-client/commit/4425a371484d3eaed66240ea8c9c1c8874e220f1) - Add `Collection.move` schema and `RestEndpoint.move` extender for moving entities between collections.

  `move` removes from collections matching the entity's existing state and adds to collections
  matching the new values (from the body/last arg). Works for both Array and Values collections.

  Path parameters filter collections by URL segments:

  ```ts
  const UserResource = resource({
    path: '/groups/:group/users/:id',
    schema: User,
  });

  // PATCH /groups/five/users/2 - moves user 2 from 'five' group to 'ten' group
  await ctrl.fetch(
    UserResource.getList.move,
    { group: 'five', id: '2' },
    { id: '2', group: 'ten' },
  );
  ```

  Search parameters filter collections by query args:

  ```ts
  const TaskResource = resource({
    path: '/tasks/:id',
    searchParams: {} as { status: string },
    schema: Task,
  });

  // PATCH /tasks/3 - moves task 3 from 'backlog' to 'in-progress'
  await ctrl.fetch(
    TaskResource.getList.move,
    { id: '3' },
    { id: '3', status: 'in-progress' },
  );
  ```

- [#3739](https://github.com/reactive/data-client/pull/3739) [`b301d4c`](https://github.com/reactive/data-client/commit/b301d4c65cd720cfe321b02162550ba758f47192) Thanks [@Dark-Brain07](https://github.com/Dark-Brain07)! - Add `toJSON()` to `NetworkError` for structured serialization in devtools and logging

- Updated dependencies [[`4425a37`](https://github.com/reactive/data-client/commit/4425a371484d3eaed66240ea8c9c1c8874e220f1)]:
  - @data-client/endpoint@0.15.7

## 0.15.6

### Patch Changes

- [#3726](https://github.com/reactive/data-client/pull/3726) [`9d94eb4`](https://github.com/reactive/data-client/commit/9d94eb46f9fd4513747ae3154298fa3b1d7487e9) - Fix `sideEffect: false` type being lost with `method: 'POST'`

  `sideEffect` set explicitly now always takes priority over `method` inference,
  including through `.extend()` chains. Previously `sideEffect: false` resolved
  to `never`, losing type information.

  ```ts
  // Before: sideEffect typed as `never` ❌
  const ep = new RestEndpoint({ method: 'POST', sideEffect: false, ... });
  // After: sideEffect typed as `false` ✓
  const ep = new RestEndpoint({ method: 'POST', sideEffect: false, ... });
  ```

## 0.15.5

### Patch Changes

- [`e571bda`](https://github.com/reactive/data-client/commit/e571bdabd136fddee7aa414c91a775c5f66ce094) Thanks [@ntucker](https://github.com/ntucker)! - Add direct exports for schema classes from `@data-client/endpoint`

  Schema classes (`Union`, `Invalidate`, `Collection`, `Query`, `Values`, `All`) can now be imported directly instead of requiring the `schema` namespace.

  #### Before

  ```ts
  import { schema } from '@data-client/endpoint';
  const myUnion = new schema.Union({ users: User, groups: Group }, 'type');
  ```

  #### After

  ```ts
  import { Union } from '@data-client/endpoint';
  const myUnion = new Union({ users: User, groups: Group }, 'type');
  ```

  The `schema` namespace export remains available for backward compatibility.

- Updated dependencies [[`e571bda`](https://github.com/reactive/data-client/commit/e571bdabd136fddee7aa414c91a775c5f66ce094)]:
  - @data-client/endpoint@0.15.5

## 0.15.4

### Patch Changes

- [#3703](https://github.com/reactive/data-client/pull/3703) [`4fe8779`](https://github.com/reactive/data-client/commit/4fe8779706cb14d9018b3375d07b486a758ccb57) Thanks [@ntucker](https://github.com/ntucker)! - Improve normalize/denormalize performance 10-15%
  - Replace `Object.keys().forEach()` with indexed for loops
  - Replace `reduce()` with spreading to direct object mutation
  - Cache getter results to avoid repeated property lookups
  - Centralize arg extraction with pre-allocated loop
  - Eliminate Map double-get pattern

  #### Microbenchmark Results

  | #   | Optimization                 | Before            | After             | Improvement      |
  | --- | ---------------------------- | ----------------- | ----------------- | ---------------- |
  | 1   | **forEach → forLoop**        | 7,164 ops/sec     | 7,331 ops/sec     | **+2.3%**        |
  | 2   | **reduce+spread → mutation** | 912 ops/sec       | 7,468 ops/sec     | **+719% (8.2x)** |
  | 3   | **getter repeated → cached** | 1,652,211 ops/sec | 4,426,994 ops/sec | **+168% (2.7x)** |
  | 4   | **slice+map → indexed**      | 33,221 ops/sec    | 54,701 ops/sec    | **+65% (1.65x)** |
  | 5   | **Map double-get → single**  | 23,046 ops/sec    | 23,285 ops/sec    | **+1%**          |

  #### Impact Summary by Codepath

  | Codepath                                   | Optimizations Applied | Expected Improvement |
  | ------------------------------------------ | --------------------- | -------------------- |
  | **normalize** (setResponse)                | 1, 2, 4               | 10-15%               |
  | **denormalize** (getResponse)              | 1, 2, 4               | 10-15%               |
  | **Controller queries** (get, getQueryMeta) | 5, 6                  | 5-10%                |

- Updated dependencies [[`4fe8779`](https://github.com/reactive/data-client/commit/4fe8779706cb14d9018b3375d07b486a758ccb57)]:
  - @data-client/endpoint@0.15.4

## 0.15.2

### Patch Changes

- [`243219c`](https://github.com/reactive/data-client/commit/243219ccc1acc8ffcbfe54e8cc4a9027819eb66a) Thanks [@ntucker](https://github.com/ntucker)! - Patch bump due to publishing mishap

- Updated dependencies [[`243219c`](https://github.com/reactive/data-client/commit/243219ccc1acc8ffcbfe54e8cc4a9027819eb66a)]:
  - @data-client/endpoint@0.15.2

## 0.15.0

### Minor Changes

- [#3685](https://github.com/reactive/data-client/pull/3685) [`56d575e`](https://github.com/reactive/data-client/commit/56d575e0219d5455df74321aee7bf85c2d490a61) Thanks [@ntucker](https://github.com/ntucker)! - Add [Union](https://dataclient.io/rest/api/Union) support to [schema.Invalidate](https://dataclient.io/rest/api/Invalidate)
  and [resource().delete](https://dataclient.io/rest/api/resource#delete) for polymorphic delete operations.

  [resource()](https://dataclient.io/rest/api/resource) with Union schema now automatically
  wraps the delete endpoint schema in Invalidate:

  ```ts
  const FeedResource = resource({
    path: '/feed/:id',
    schema: FeedUnion, // Union of Post, Comment, etc.
  });
  // FeedResource.delete automatically uses Invalidate(FeedUnion)
  await ctrl.fetch(FeedResource.delete, { id: '123' });
  ```

  For standalone endpoints, use `schema.Invalidate` directly:

  ```ts
  new schema.Invalidate(MyUnionSchema);
  ```

- [#3461](https://github.com/reactive/data-client/pull/3461) [`939a4b0`](https://github.com/reactive/data-client/commit/939a4b01127ea1df9b4653931593487e4b0c23a2) Thanks [@ntucker](https://github.com/ntucker)! - Add delegate.INVALID to queryKey

  This is used in schema.All.queryKey().

  #### Before

  ```ts
  queryKey(args: any, unvisit: any, delegate: IQueryDelegate): any {
    if (!found) return INVALID;
  }
  ```

  #### After

  ```ts
  queryKey(args: any, unvisit: any, delegate: IQueryDelegate): any {
    if (!found) return delegate.INVALID;
  }
  ```

- [#3461](https://github.com/reactive/data-client/pull/3461) [`939a4b0`](https://github.com/reactive/data-client/commit/939a4b01127ea1df9b4653931593487e4b0c23a2) Thanks [@ntucker](https://github.com/ntucker)! - Add delegate.invalidate() to normalization

  #### Before

  ```ts
  normalize(
    input: any,
    parent: any,
    key: string | undefined,
    args: any[],
    visit: (...args: any) => any,
    delegate: INormalizeDelegate,
  ): string {
    delegate.setEntity(this as any, pk, INVALID);
  }
  ```

  #### After

  ```ts
  normalize(
    input: any,
    parent: any,
    key: string | undefined,
    args: any[],
    visit: (...args: any) => any,
    delegate: INormalizeDelegate,
  ): string {
    delegate.invalidate(this as any, pk);
  }
  ```

- [#3449](https://github.com/reactive/data-client/pull/3449) [`1f491a9`](https://github.com/reactive/data-client/commit/1f491a9e0082dca64ad042aaf7d377e17f459ae7) Thanks [@ntucker](https://github.com/ntucker)! - BREAKING CHANGE: schema.normalize(...args, addEntity, getEntity, checkLoop) -> schema.normalize(...args, delegate)

  We consolidate all 'callback' functions during recursion calls into a single 'delegate' argument.

  ```ts
  /** Helpers during schema.normalize() */
  export interface INormalizeDelegate {
    /** Action meta-data for this normalize call */
    readonly meta: { fetchedAt: number; date: number; expiresAt: number };
    /** Gets any previously normalized entity from store */
    getEntity: GetEntity;
    /** Updates an entity using merge lifecycles when it has previously been set */
    mergeEntity(
      schema: Mergeable & { indexes?: any },
      pk: string,
      incomingEntity: any,
    ): void;
    /** Sets an entity overwriting any previously set values */
    setEntity(
      schema: { key: string; indexes?: any },
      pk: string,
      entity: any,
      meta?: { fetchedAt: number; date: number; expiresAt: number },
    ): void;
    /** Returns true when we're in a cycle, so we should not continue recursing */
    checkLoop(key: string, pk: string, input: object): boolean;
  }
  ```

  #### Before

  ```ts
  addEntity(this, processedEntity, id);
  ```

  #### After

  ```ts
  delegate.mergeEntity(this, id, processedEntity);
  ```

- [#3461](https://github.com/reactive/data-client/pull/3461) [`939a4b0`](https://github.com/reactive/data-client/commit/939a4b01127ea1df9b4653931593487e4b0c23a2) Thanks [@ntucker](https://github.com/ntucker)! - Remove `INVALID` symbol export

  Schemas can use delegate.invalidate() in normalize() or return delegate.INVALID in queryKey().

- [#3449](https://github.com/reactive/data-client/pull/3449) [`1f491a9`](https://github.com/reactive/data-client/commit/1f491a9e0082dca64ad042aaf7d377e17f459ae7) Thanks [@ntucker](https://github.com/ntucker)! - BREAKING CHANGE: schema.queryKey(args, queryKey, getEntity, getIndex) -> schema.queryKey(args, unvisit, delegate)
  BREAKING CHANGE: delegate.getIndex() returns the index directly, rather than object.

  We consolidate all 'callback' functions during recursion calls into a single 'delegate' argument.

  Our recursive call is renamed from queryKey to unvisit, and does not require the last two arguments.

  ```ts
  /** Accessors to the currently processing state while building query */
  export interface IQueryDelegate {
    getEntity: GetEntity;
    getIndex: GetIndex;
  }
  ```

  #### Before

  ```ts
  queryKey(args, queryKey, getEntity, getIndex) {
    getIndex(schema.key, indexName, value)[value];
    getEntity(this.key, id);
    return queryKey(this.schema, args, getEntity, getIndex);
  }
  ```

  #### After

  ```ts
  queryKey(args, unvisit, delegate) {
    delegate.getIndex(schema.key, indexName, value);
    delegate.getEntity(this.key, id);
    return unvisit(this.schema, args);
  }
  ```

### Patch Changes

- [#3449](https://github.com/reactive/data-client/pull/3449) [`1f491a9`](https://github.com/reactive/data-client/commit/1f491a9e0082dca64ad042aaf7d377e17f459ae7) Thanks [@ntucker](https://github.com/ntucker)! - Fix: ensure string id in Entity set when process returns undefined (meaning INVALID)

- [`e2fff91`](https://github.com/reactive/data-client/commit/e2fff911e21864620dba8d9470142af9130aafed) Thanks [@ntucker](https://github.com/ntucker)! - fix: Collection.remove with Unions

- [#3635](https://github.com/reactive/data-client/pull/3635) [`63ee107`](https://github.com/reactive/data-client/commit/63ee107be9d559e6ccbcb2f9c6fd7bf83165e551) Thanks [@ntucker](https://github.com/ntucker)! - Fix `getPage` types when paginationField is in body

  ```ts
  const ep = new RestEndpoint({
    path: '/rpc',
    method: 'POST',
    body: {} as { page?: number; method: string },
    paginationField: 'page',
  });
  // Before: ep.getPage({ page: 2 }, { method: 'get' }) ❌
  // After:  ep.getPage({ page: 2, method: 'get' })     ✓
  ```

- [#3684](https://github.com/reactive/data-client/pull/3684) [`53de2ee`](https://github.com/reactive/data-client/commit/53de2eefb891a4783e3f1c7724dc25dc9e6a8e1f) Thanks [@ntucker](https://github.com/ntucker)! - Optimize normalization performance with faster loops and Set-based cycle detection

- [#3560](https://github.com/reactive/data-client/pull/3560) [`ba31c9b`](https://github.com/reactive/data-client/commit/ba31c9b2d3c4ec5620bb64e49daf9b18994b9290) Thanks [@ntucker](https://github.com/ntucker)! - Add Collection.remove

  ```ts
  ctrl.set(MyResource.getList.schema.remove, { id });
  ```

  ```ts
  const removeItem = MyResource.delete.extend({
    schema: MyResource.getList.schema.remove,
  });
  ```

- [#3558](https://github.com/reactive/data-client/pull/3558) [`fcb7d7d`](https://github.com/reactive/data-client/commit/fcb7d7db8061c2a7e12632071ecb9c6ddd8d154f) Thanks [@ntucker](https://github.com/ntucker)! - Normalize delegate.invalidate() first argument only has `key` param.

  `indexes` optional param no longer provided as it was never used.

  ```ts
  normalize(
    input: any,
    parent: any,
    key: string | undefined,
    args: any[],
    visit: (...args: any) => any,
    delegate: INormalizeDelegate,
  ): string {
    delegate.invalidate({ key: this._entity.key }, pk);
    return pk;
  }
  ```

- [#3623](https://github.com/reactive/data-client/pull/3623) [`8be3b17`](https://github.com/reactive/data-client/commit/8be3b1725707c4bcbf0fdd6e72ddd78d85fd125f) Thanks [@ntucker](https://github.com/ntucker)! - Add RestEndpoint.remove

  Creates a PATCH endpoint that both removes an entity from a Collection and updates the entity with the provided body data.

  ```ts
  const getTodos = new RestEndpoint({
    path: '/todos',
    schema: new schema.Collection([Todo]),
  });

  // Removes Todo from collection AND updates it with new data
  await ctrl.fetch(
    getTodos.remove,
    {},
    { id: '123', title: 'Done', completed: true },
  );
  ```

  ```ts
  // Remove user from group list and update their group
  await ctrl.fetch(
    UserResource.getList.remove,
    { group: 'five' },
    { id: 2, username: 'user2', group: 'newgroup' },
  );
  // User is removed from the 'five' group list
  // AND the user entity is updated with group: 'newgroup'
  ```

- [#3558](https://github.com/reactive/data-client/pull/3558) [`fcb7d7d`](https://github.com/reactive/data-client/commit/fcb7d7db8061c2a7e12632071ecb9c6ddd8d154f) Thanks [@ntucker](https://github.com/ntucker)! - Unions can query() without type discriminator

  #### Before

  ```tsx
  // @ts-expect-error
  const event = useQuery(EventUnion, { id });
  // event is undefined
  const newsEvent = useQuery(EventUnion, { id, type: 'news' });
  // newsEvent is found
  ```

  #### After

  ```tsx
  const event = useQuery(EventUnion, { id });
  // event is found
  const newsEvent = useQuery(EventUnion, { id, type: 'news' });
  // newsEvent is found
  ```

- [`35552c7`](https://github.com/reactive/data-client/commit/35552c716e3b688d69212654f9f95a05ea26a7f8) Thanks [@ntucker](https://github.com/ntucker)! - Include GPT link badge in readme

- Updated dependencies [[`1f491a9`](https://github.com/reactive/data-client/commit/1f491a9e0082dca64ad042aaf7d377e17f459ae7), [`56d575e`](https://github.com/reactive/data-client/commit/56d575e0219d5455df74321aee7bf85c2d490a61), [`e2fff91`](https://github.com/reactive/data-client/commit/e2fff911e21864620dba8d9470142af9130aafed), [`939a4b0`](https://github.com/reactive/data-client/commit/939a4b01127ea1df9b4653931593487e4b0c23a2), [`939a4b0`](https://github.com/reactive/data-client/commit/939a4b01127ea1df9b4653931593487e4b0c23a2), [`53de2ee`](https://github.com/reactive/data-client/commit/53de2eefb891a4783e3f1c7724dc25dc9e6a8e1f), [`ba31c9b`](https://github.com/reactive/data-client/commit/ba31c9b2d3c4ec5620bb64e49daf9b18994b9290), [`fcb7d7d`](https://github.com/reactive/data-client/commit/fcb7d7db8061c2a7e12632071ecb9c6ddd8d154f), [`1f491a9`](https://github.com/reactive/data-client/commit/1f491a9e0082dca64ad042aaf7d377e17f459ae7), [`4dde1d6`](https://github.com/reactive/data-client/commit/4dde1d616e38d59b645573b12bbaba2f9cac7895), [`bab907c`](https://github.com/reactive/data-client/commit/bab907ce824c0f7da961d74c9fb8b64ce7c95141), [`5699005`](https://github.com/reactive/data-client/commit/5699005700206306bc70ff8237bf7ceaac241b82), [`939a4b0`](https://github.com/reactive/data-client/commit/939a4b01127ea1df9b4653931593487e4b0c23a2), [`fcb7d7d`](https://github.com/reactive/data-client/commit/fcb7d7db8061c2a7e12632071ecb9c6ddd8d154f), [`1f491a9`](https://github.com/reactive/data-client/commit/1f491a9e0082dca64ad042aaf7d377e17f459ae7), [`35552c7`](https://github.com/reactive/data-client/commit/35552c716e3b688d69212654f9f95a05ea26a7f8)]:
  - @data-client/endpoint@0.15.0

## 0.14.25

### Patch Changes

- [#3417](https://github.com/reactive/data-client/pull/3417) [`a6af54c`](https://github.com/reactive/data-client/commit/a6af54c1bc2193de47c96938df74b243cb82bfe6) Thanks [@ntucker](https://github.com/ntucker)! - Update getOptimisticResponse snapshot types to include getResponseMeta

- [#3407](https://github.com/reactive/data-client/pull/3407) [`d84899d`](https://github.com/reactive/data-client/commit/d84899de4fb784375ab7a34fff6fe23a2ed98037) Thanks [@ntucker](https://github.com/ntucker)! - Support dynamic invalidation/deletes

  Returning `undefined` from [Entity.process](https://dataclient.io/rest/api/Entity#process)
  will cause the [Entity](https://dataclient.io/rest/api/Entity) to be [invalidated](https://dataclient.io/docs/concepts/expiry-policy#invalidate-entity).
  This this allows us to invalidate dynamically; based on the particular response data.

  ```ts
  class PriceLevel extends Entity {
    price = 0;
    amount = 0;

    pk() {
      return this.price;
    }

    static process(
      input: [number, number],
      parent: any,
      key: string | undefined,
    ): any {
      const [price, amount] = input;
      if (amount === 0) return undefined;
      return { price, amount };
    }
  }
  ```

- Updated dependencies [[`a6af54c`](https://github.com/reactive/data-client/commit/a6af54c1bc2193de47c96938df74b243cb82bfe6), [`d84899d`](https://github.com/reactive/data-client/commit/d84899de4fb784375ab7a34fff6fe23a2ed98037)]:
  - @data-client/endpoint@0.14.25

## 0.14.22

### Patch Changes

- [#3390](https://github.com/reactive/data-client/pull/3390) [`32cccdb`](https://github.com/reactive/data-client/commit/32cccdb921cd8d7643b641a9e8872aa89782a94a) Thanks [@ntucker](https://github.com/ntucker)! - Improve performance by using Map() instead of Object for unbounded keys

## 0.14.21

### Patch Changes

- [#3384](https://github.com/reactive/data-client/pull/3384) [`24ad679`](https://github.com/reactive/data-client/commit/24ad679f58c7eb0d0e6917790b4ebb5ee234e1d3) Thanks [@ntucker](https://github.com/ntucker)! - Reduce bundle sizes by 30% by removing unneeded polyfills

- Updated dependencies [[`24ad679`](https://github.com/reactive/data-client/commit/24ad679f58c7eb0d0e6917790b4ebb5ee234e1d3)]:
  - @data-client/endpoint@0.14.21

## 0.14.20

### Patch Changes

- [`c3514c6`](https://github.com/reactive/data-client/commit/c3514c6afa2cd76dafa02adcfad6f6481a34b5de) Thanks [@ntucker](https://github.com/ntucker)! - Remove unnecessary polyfills in build

- Updated dependencies [[`c3514c6`](https://github.com/reactive/data-client/commit/c3514c6afa2cd76dafa02adcfad6f6481a34b5de)]:
  - @data-client/endpoint@0.14.20

## 0.14.19

### Patch Changes

- [`cb4fb92`](https://github.com/reactive/data-client/commit/cb4fb922e305502ba8ab99c99b6012e753a87a3a) Thanks [@ntucker](https://github.com/ntucker)! - Remove typing redundancy

- [#3371](https://github.com/reactive/data-client/pull/3371) [`679d76a`](https://github.com/reactive/data-client/commit/679d76a36234dcf5993c0358f94d7e1db0505cc6) Thanks [@ntucker](https://github.com/ntucker)! - Add react-native entry to package.json exports

- [#3353](https://github.com/reactive/data-client/pull/3353) [`165afed`](https://github.com/reactive/data-client/commit/165afed083c0c63e9356bc8d1ee30dee8b916ed6) Thanks [@renovate](https://github.com/apps/renovate)! - Polyfills no longer pollute global scope

- Updated dependencies [[`cb4fb92`](https://github.com/reactive/data-client/commit/cb4fb922e305502ba8ab99c99b6012e753a87a3a), [`679d76a`](https://github.com/reactive/data-client/commit/679d76a36234dcf5993c0358f94d7e1db0505cc6), [`165afed`](https://github.com/reactive/data-client/commit/165afed083c0c63e9356bc8d1ee30dee8b916ed6)]:
  - @data-client/endpoint@0.14.19

## 0.14.18

### Patch Changes

- [#3333](https://github.com/reactive/data-client/pull/3333) [`1777546`](https://github.com/reactive/data-client/commit/17775462d236bf714f518b861a63d5ae9f1f6357) Thanks [@renovate](https://github.com/apps/renovate)! - Resource.extend() compatibility with TypeScript 5

  Previously [extending existing members](https://dataclient.io/rest/api/resource#extend-override) with no
  typed overrides (like [path](https://dataclient.io/rest/api/resource#path)) would not work starting with
  TypeScript 5.7.

  ```ts
  const UserResource = UserResourceBase.extend({
    partialUpdate: {
      getOptimisticResponse(snap, params, body) {
        params.id;
        params.group;
        // @ts-expect-error
        params.nothere;
        return {
          id: params.id,
          ...body,
        };
      },
    },
  });
  ```

## 0.14.17

### Patch Changes

- [#3281](https://github.com/reactive/data-client/pull/3281) [`99cd041`](https://github.com/reactive/data-client/commit/99cd04152532e13d8fb092ea800d381391d5aacd) Thanks [@ntucker](https://github.com/ntucker)! - Collections work with nested args

  This fixes [integration with qs library](https://dataclient.io/rest/api/RestEndpoint#using-qs-library) and more complex search parameters.

- [`25be07f`](https://github.com/reactive/data-client/commit/25be07f51c501003330d758993542bee3bd804e1) Thanks [@ntucker](https://github.com/ntucker)! - Update README to not say 'mixin' twice

- Updated dependencies [[`99cd041`](https://github.com/reactive/data-client/commit/99cd04152532e13d8fb092ea800d381391d5aacd)]:
  - @data-client/endpoint@0.14.17

## 0.14.16

### Patch Changes

- [`4580e62`](https://github.com/reactive/data-client/commit/4580e628764ab43de3e4607f8584bc6cb4173021) Thanks [@ntucker](https://github.com/ntucker)! - Update docstring for EntityMixin

- [#3243](https://github.com/reactive/data-client/pull/3243) [`43a955c`](https://github.com/reactive/data-client/commit/43a955c18684b4e0f5c1d79b2504e8ad2910816b) Thanks [@ntucker](https://github.com/ntucker)! - `schema.Entity` -> [EntityMixin](https://dataclient.io/rest/api/EntityMixin)

  ```ts
  import { EntityMixin } from '@data-client/rest';

  export class Article {
    id = '';
    title = '';
    content = '';
    tags: string[] = [];
  }

  export class ArticleEntity extends EntityMixin(Article) {}
  ```

  We keep `schema.Entity` for legacy, and add schema.EntityMixin and [EntityMixin](https://dataclient.io/rest/api/EntityMixin) as direct export

- Updated dependencies [[`4580e62`](https://github.com/reactive/data-client/commit/4580e628764ab43de3e4607f8584bc6cb4173021), [`1f7b191`](https://github.com/reactive/data-client/commit/1f7b1913e9301230d9fdae23baba9e3c582e005c), [`43a955c`](https://github.com/reactive/data-client/commit/43a955c18684b4e0f5c1d79b2504e8ad2910816b)]:
  - @data-client/endpoint@0.14.16

## 0.14.13

### Patch Changes

- [#3215](https://github.com/reactive/data-client/pull/3215) [`e74f7dc`](https://github.com/reactive/data-client/commit/e74f7dc0750fdf32e455bf2c36eff119afba6476) Thanks [@renovate](https://github.com/apps/renovate)! - Update path-to-regexp for [CVE-2024-45296](https://redirect.github.com/pillarjs/path-to-regexp/security/advisories/GHSA-9wv6-86v2-598j)

## 0.14.12

### Patch Changes

- [`2b10a49`](https://github.com/reactive/data-client/commit/2b10a4997093570b96533ef7b99c89be722a6fa7) Thanks [@ntucker](https://github.com/ntucker)! - Add ResourceInterface export

- [`3b337e7`](https://github.com/reactive/data-client/commit/3b337e74e3f22f2fe48f6eb37084bbf58859bbe1) Thanks [@ntucker](https://github.com/ntucker)! - Add schema table to README

- [`11d4ccf`](https://github.com/reactive/data-client/commit/11d4ccfb4c630c25b847bf59ca1028eed8c2369e) Thanks [@ntucker](https://github.com/ntucker)! - Fix: Collection adders (push/unshift) should _not_ be Queryable

- Updated dependencies [[`3b337e7`](https://github.com/reactive/data-client/commit/3b337e74e3f22f2fe48f6eb37084bbf58859bbe1), [`11d4ccf`](https://github.com/reactive/data-client/commit/11d4ccfb4c630c25b847bf59ca1028eed8c2369e)]:
  - @data-client/endpoint@0.14.12

## 0.14.11

### Patch Changes

- [`87a65ba`](https://github.com/reactive/data-client/commit/87a65ba8b5f266a299ac3d9c78b6605deee5f4e2) Thanks [@ntucker](https://github.com/ntucker)! - Fix Entity types for TS 4.0 and below

- [`a436050`](https://github.com/reactive/data-client/commit/a43605035d3791ad73393ce229ed85c8e8f2cb88) Thanks [@ntucker](https://github.com/ntucker)! - Fix README markup

- Updated dependencies [[`87a65ba`](https://github.com/reactive/data-client/commit/87a65ba8b5f266a299ac3d9c78b6605deee5f4e2)]:
  - @data-client/endpoint@0.14.11

## 0.14.10

### Patch Changes

- [#3188](https://github.com/reactive/data-client/pull/3188) [`cde7121`](https://github.com/reactive/data-client/commit/cde71212706a46bbfd13dd76e8cfc478b22fe2ab) Thanks [@ntucker](https://github.com/ntucker)! - Do not require [Entity.pk()](https://dataclient.io/rest/api/Entity#pk)

  Default implementation uses `this.id`

- [#3188](https://github.com/reactive/data-client/pull/3188) [`cde7121`](https://github.com/reactive/data-client/commit/cde71212706a46bbfd13dd76e8cfc478b22fe2ab) Thanks [@ntucker](https://github.com/ntucker)! - Update README to remove Entity.pk() when it is default ('id')

- Updated dependencies [[`cde7121`](https://github.com/reactive/data-client/commit/cde71212706a46bbfd13dd76e8cfc478b22fe2ab), [`cde7121`](https://github.com/reactive/data-client/commit/cde71212706a46bbfd13dd76e8cfc478b22fe2ab)]:
  - @data-client/endpoint@0.14.10

## 0.14.9

### Patch Changes

- [`c263931`](https://github.com/reactive/data-client/commit/c26393176518550a16a2e71aea55a8379f30385e) Thanks [@ntucker](https://github.com/ntucker)! - Update README

- [`366c609`](https://github.com/reactive/data-client/commit/366c609dbda9707f8ecfaef5020c67dd1c7e262b) Thanks [@ntucker](https://github.com/ntucker)! - Make NetworkError messages include more useful information

  Add URL so it's clear _what_ is causing issues when response is
  not 'ok'

## 0.14.8

### Patch Changes

- [`bad1fb9`](https://github.com/reactive/data-client/commit/bad1fb909f8d60f19450bbf40df00d90e03a61c2) Thanks [@ntucker](https://github.com/ntucker)! - Update package description

## 0.14.6

### Patch Changes

- [#3165](https://github.com/reactive/data-client/pull/3165) [`3fa9eb9`](https://github.com/reactive/data-client/commit/3fa9eb907d8760171da065168796b87e802d6666) Thanks [@ntucker](https://github.com/ntucker)! - [Query](https://dataclient.io/rest/api/Query) can take [Object Schemas](https://dataclient.io/rest/api/Object)

  This enables joining arbitrary objects (whose pk works with the same arguments.)

  ```ts
  class Ticker extends Entity {
    product_id = '';
    price = 0;

    pk(): string {
      return this.product_id;
    }
  }
  class Stats extends Entity {
    product_id = '';
    last = 0;

    pk(): string {
      return this.product_id;
    }
  }
  const queryPrice = new schema.Query(
    { ticker: Ticker, stats: Stats },
    ({ ticker, stats }) => ticker?.price ?? stats?.last,
  );
  ```

- Updated dependencies [[`3fa9eb9`](https://github.com/reactive/data-client/commit/3fa9eb907d8760171da065168796b87e802d6666)]:
  - @data-client/endpoint@0.14.6

## 0.14.4

### Patch Changes

- [`0adad92`](https://github.com/reactive/data-client/commit/0adad9209265c388eb6d334afe681610bccfb877) Thanks [@ntucker](https://github.com/ntucker)! - Update debugging link

- Updated dependencies [[`0adad92`](https://github.com/reactive/data-client/commit/0adad9209265c388eb6d334afe681610bccfb877)]:
  - @data-client/endpoint@0.14.4

## 0.14.3

### Patch Changes

- [`501cb82`](https://github.com/reactive/data-client/commit/501cb82c999030fd269b40eb760ae0dda568c569) Thanks [@ntucker](https://github.com/ntucker)! - Remove name in toJSON() for Entities

- [`501cb82`](https://github.com/reactive/data-client/commit/501cb82c999030fd269b40eb760ae0dda568c569) Thanks [@ntucker](https://github.com/ntucker)! - Add toString() to Collection

- [`3058a8a`](https://github.com/reactive/data-client/commit/3058a8a7738eeea0a197c9ba2db2e8ee51e2fca3) Thanks [@ntucker](https://github.com/ntucker)! - Collection non-known (not Array/Values) key format improvement

  Now wraps in parens `()`: "(Todo)"

- [#3158](https://github.com/reactive/data-client/pull/3158) [`34e2e51`](https://github.com/reactive/data-client/commit/34e2e51e89908649f1297c23a71cdafecf1d3b6f) Thanks [@ntucker](https://github.com/ntucker)! - createResource() -> [resource()](https://dataclient.io/rest/api/resource)

  Note: `createResource` is still exported (it is the same)

- Updated dependencies [[`501cb82`](https://github.com/reactive/data-client/commit/501cb82c999030fd269b40eb760ae0dda568c569), [`501cb82`](https://github.com/reactive/data-client/commit/501cb82c999030fd269b40eb760ae0dda568c569), [`3058a8a`](https://github.com/reactive/data-client/commit/3058a8a7738eeea0a197c9ba2db2e8ee51e2fca3)]:
  - @data-client/endpoint@0.14.3

## 0.14.1

### Patch Changes

- [#3151](https://github.com/reactive/data-client/pull/3151) [`428d618`](https://github.com/reactive/data-client/commit/428d618ce057d4eef23592a64ec9d1c6fb82f43f) Thanks [@ntucker](https://github.com/ntucker)! - Collection.key is shorter and more readable

  `[Todo]` for Arrays or `{Todo}` for Values

- [#3151](https://github.com/reactive/data-client/pull/3151) [`428d618`](https://github.com/reactive/data-client/commit/428d618ce057d4eef23592a64ec9d1c6fb82f43f) Thanks [@ntucker](https://github.com/ntucker)! - fix: Collection.key robust against class name mangling

- [#3151](https://github.com/reactive/data-client/pull/3151) [`428d618`](https://github.com/reactive/data-client/commit/428d618ce057d4eef23592a64ec9d1c6fb82f43f) Thanks [@ntucker](https://github.com/ntucker)! - Collections now work with polymorhpic schemas like Union

  Collections.key on polymorphic types lists their possible Entity keys: `[PushEvent;PullRequestEvent]`

- Updated dependencies [[`428d618`](https://github.com/reactive/data-client/commit/428d618ce057d4eef23592a64ec9d1c6fb82f43f), [`428d618`](https://github.com/reactive/data-client/commit/428d618ce057d4eef23592a64ec9d1c6fb82f43f), [`428d618`](https://github.com/reactive/data-client/commit/428d618ce057d4eef23592a64ec9d1c6fb82f43f)]:
  - @data-client/endpoint@0.14.1

## 0.14.0

### Minor Changes

- [#3134](https://github.com/reactive/data-client/pull/3134) [`2ad1811`](https://github.com/reactive/data-client/commit/2ad1811149cdc419f6462ace08efdb7766195b36) Thanks [@ntucker](https://github.com/ntucker)! - Change Schema.normalize `visit()` interface; removing non-contextual arguments.

  ```ts
  /** Visits next data + schema while recurisvely normalizing */
  export interface Visit {
    (schema: any, value: any, parent: any, key: any, args: readonly any[]): any;
    creating?: boolean;
  }
  ```

  This results in a 10% normalize performance boost.

  ```ts title="Before"
  processedEntity[key] = visit(
    processedEntity[key],
    processedEntity,
    key,
    this.schema[key],
    addEntity,
    visitedEntities,
    storeEntities,
    args,
  );
  ```

  ```ts title="After"
  processedEntity[key] = visit(
    this.schema[key],
    processedEntity[key],
    processedEntity,
    key,
    args,
  );
  ```

  The information needed from these arguments are provided by [closing](<https://en.wikipedia.org/wiki/Closure_(computer_programming)>) `visit()` around them.

- [#3134](https://github.com/reactive/data-client/pull/3134) [`2ad1811`](https://github.com/reactive/data-client/commit/2ad1811149cdc419f6462ace08efdb7766195b36) Thanks [@ntucker](https://github.com/ntucker)! - Change Schema.normalize interface from direct data access, to using functions like `getEntity`

  ```ts
  interface SchemaSimple {
    normalize(
      input: any,
      parent: any,
      key: any,
      args: any[],
      visit: (
        schema: any,
        value: any,
        parent: any,
        key: any,
        args: readonly any[],
      ) => any,
      addEntity: (...args: any) => any,
      getEntity: (...args: any) => any,
      checkLoop: (...args: any) => any,
    ): any;
  }
  ```

  We also add `checkLoop()`, which moves some logic in [Entity](https://dataclient.io/rest/api/Entity)
  to the core normalize algorithm.

  ```ts
  /** Returns true if a circular reference is found */
  export interface CheckLoop {
    (entityKey: string, pk: string, input: object): boolean;
  }
  ```

- [#3134](https://github.com/reactive/data-client/pull/3134) [`2ad1811`](https://github.com/reactive/data-client/commit/2ad1811149cdc419f6462ace08efdb7766195b36) Thanks [@ntucker](https://github.com/ntucker)! - Change Schema.denormalize `unvisit` to have [schema](https://dataclient.io/rest/api/schema) argument first.

  ```ts
  interface SchemaSimple {
    denormalize(
      input: {},
      args: readonly any[],
      unvisit: (schema: any, input: any) => any,
    ): T;
  }
  ```

### Patch Changes

- Updated dependencies [[`2ad1811`](https://github.com/reactive/data-client/commit/2ad1811149cdc419f6462ace08efdb7766195b36), [`2ad1811`](https://github.com/reactive/data-client/commit/2ad1811149cdc419f6462ace08efdb7766195b36), [`2ad1811`](https://github.com/reactive/data-client/commit/2ad1811149cdc419f6462ace08efdb7766195b36), [`7bd322d`](https://github.com/reactive/data-client/commit/7bd322d585b0893561b3ffb3c5ad47b2764c18bd)]:
  - @data-client/endpoint@0.14.0

## 0.13.4

### Patch Changes

- [`720ff0c`](https://github.com/reactive/data-client/commit/720ff0c3d833ff4d1eb5020694131e87282b585d) Thanks [@ntucker](https://github.com/ntucker)! - Update keywords

- Updated dependencies [[`720ff0c`](https://github.com/reactive/data-client/commit/720ff0c3d833ff4d1eb5020694131e87282b585d)]:
  - @data-client/endpoint@0.13.4

## 0.12.8

### Patch Changes

- [`9c04770`](https://github.com/reactive/data-client/commit/9c04770414e52cfc932878581736a3a93721ab7c) Thanks [@ntucker](https://github.com/ntucker)! - Improve clarity of Resource method docstrings

## 0.12.7

### Patch Changes

- [`4bc9145`](https://github.com/reactive/data-client/commit/4bc914574116d285f81546ffe37ead3e8aa339dc) Thanks [@ntucker](https://github.com/ntucker)! - Improve readability of Collection generics by naming DefaultArgs

- [#3063](https://github.com/reactive/data-client/pull/3063) [`2080c87`](https://github.com/reactive/data-client/commit/2080c8751df147a839f03eade9804d57291d12fb) Thanks [@ntucker](https://github.com/ntucker)! - Polymorphic (Union) types should still denormalize when handling passthrough (non-normalized) data

  When denormalizing non-normalized (like return of ctrl.fetch), it is still expected to handle
  all steps like constructing class instances if possible. However, to do this for Polymorphic
  types we need to fallback to using part of the normalize process to find out _which_ schema
  to use for the remainder of denormalization.

- [`4bc9145`](https://github.com/reactive/data-client/commit/4bc914574116d285f81546ffe37ead3e8aa339dc) Thanks [@ntucker](https://github.com/ntucker)! - Add docstrings to schema constructors

- [`bf1f9bb`](https://github.com/reactive/data-client/commit/bf1f9bbfce9efc293cdb40939227795ea750452f) Thanks [@ntucker](https://github.com/ntucker)! - Add docstrings to RestGenerics, ResourceGenerics, and RestEndpointOptions members

- Updated dependencies [[`4bc9145`](https://github.com/reactive/data-client/commit/4bc914574116d285f81546ffe37ead3e8aa339dc), [`2080c87`](https://github.com/reactive/data-client/commit/2080c8751df147a839f03eade9804d57291d12fb), [`4bc9145`](https://github.com/reactive/data-client/commit/4bc914574116d285f81546ffe37ead3e8aa339dc)]:
  - @data-client/endpoint@0.12.7

## 0.12.6

### Patch Changes

- [`9551e9a`](https://github.com/reactive/data-client/commit/9551e9aa64f16562e440bb8393e5a4b31b638fb5) Thanks [@ntucker](https://github.com/ntucker)! - Export RestEndpoint interface type to remove TS warnings about portability

- [`19832bc`](https://github.com/reactive/data-client/commit/19832bc1ee15805788697748b275c134ea81ebf6) Thanks [@ntucker](https://github.com/ntucker)! - Add docstrings to Collection methods

- Updated dependencies [[`19832bc`](https://github.com/reactive/data-client/commit/19832bc1ee15805788697748b275c134ea81ebf6)]:
  - @data-client/endpoint@0.12.6

## 0.12.5

### Patch Changes

- [`019e1bc`](https://github.com/reactive/data-client/commit/019e1bc2ecf3651540f905912aaae30c545dd521) Thanks [@ntucker](https://github.com/ntucker)! - Improve readability of RestEndpoint instance types

  Now `new RestEndpoint()` will show a `RestEndpoint` type with the relevant
  options.

## 0.12.4

### Patch Changes

- [`a6b4f4a`](https://github.com/reactive/data-client/commit/a6b4f4aabbfd06f5106a96e809a6c1a5e7045172) Thanks [@ntucker](https://github.com/ntucker)! - Support + and \* in RestEndpoint.path

- [`a6b4f4a`](https://github.com/reactive/data-client/commit/a6b4f4aabbfd06f5106a96e809a6c1a5e7045172) Thanks [@ntucker](https://github.com/ntucker)! - Add support for {} to RestEndpoint.path

  ```ts
  const getThing = new RestEndpoint({
    path: '/:attr1?{-:attr2}?{-:attr3}?',
  });

  getThing({ attr1: 'hi' });
  getThing({ attr2: 'hi' });
  getThing({ attr3: 'hi' });
  getThing({ attr1: 'hi', attr3: 'ho' });
  getThing({ attr2: 'hi', attr3: 'ho' });
  ```

## 0.12.3

### Patch Changes

- [`00d4205`](https://github.com/reactive/data-client/commit/00d4205f03562cfe4acd18215718e23ae5466b8d) Thanks [@ntucker](https://github.com/ntucker)! - Add funding package.json field

- [`8a8634c`](https://github.com/reactive/data-client/commit/8a8634c7a263cf99e9ce426b2c9b92fd2a12a259) Thanks [@ntucker](https://github.com/ntucker)! - Update SnapshotInterface to include improvements in getError type

- Updated dependencies [[`00d4205`](https://github.com/reactive/data-client/commit/00d4205f03562cfe4acd18215718e23ae5466b8d), [`8a8634c`](https://github.com/reactive/data-client/commit/8a8634c7a263cf99e9ce426b2c9b92fd2a12a259)]:
  - @data-client/endpoint@0.12.3

## 0.11.5

### Patch Changes

- [#3028](https://github.com/reactive/data-client/pull/3028) [`b173c52`](https://github.com/reactive/data-client/commit/b173c52aa00bc9d57337983f01b2ce5c8ee84f6f) Thanks [@ntucker](https://github.com/ntucker)! - Warn for capitalization mistakes when calling createResource()

  `Endpoint` and `Collection` are both capitalized because they
  are classes. However, this may not be intuitive since other arguments are lower-first. Let's add a console.warn() to help
  guide, since this may be intentional?

  ```ts
  export const UserResource = createResource({
    urlPrefix: CONFIG.API_ROOT,
    path: '/users/:id',
    schema: User,
    // this should be 'Endpoint:'
    endpoint: AuthedEndpoint,
  });
  ```

## 0.11.3

### Patch Changes

- [#3017](https://github.com/reactive/data-client/pull/3017) [`ce164d2`](https://github.com/reactive/data-client/commit/ce164d286c8afcb2593a86abbf23948a08aa40ba) Thanks [@ntucker](https://github.com/ntucker)! - Queries pass-through suspense rather than ever being undefined
  - [useSuspense()](https://dataclient.io/docs/api/useSuspense) return values will not be nullable
  - [useQuery()](https://dataclient.io/docs/api/useQuery) will still be nullable due to it handling `INVALID` as `undefined` return
  - [Query.process](https://dataclient.io/rest/api/Query#process) does not need to handle nullable cases

- Updated dependencies [[`ce164d2`](https://github.com/reactive/data-client/commit/ce164d286c8afcb2593a86abbf23948a08aa40ba)]:
  - @data-client/endpoint@0.11.3

## 0.11.1

### Patch Changes

- [#3006](https://github.com/reactive/data-client/pull/3006) [`13c6466`](https://github.com/reactive/data-client/commit/13c64662bce3813869140bc709badffc59929c5e) Thanks [@ntucker](https://github.com/ntucker)! - Endpoint.sideEffect can be `false`

- [#3004](https://github.com/reactive/data-client/pull/3004) [`18ec81e`](https://github.com/reactive/data-client/commit/18ec81eaacd1ab6e860653fa23ea95a0f5889e36) Thanks [@ntucker](https://github.com/ntucker)! - Allow sideEffect overrides when using .extend()

- Updated dependencies [[`13c6466`](https://github.com/reactive/data-client/commit/13c64662bce3813869140bc709badffc59929c5e)]:
  - @data-client/endpoint@0.11.1

## 0.11.0

[Release notes and migration guide](https://dataclient.io/blog/2024/04/08/v0.11-queries-querable-usequery)

### Minor Changes

- [#2921](https://github.com/reactive/data-client/pull/2921) [`6e55026`](https://github.com/reactive/data-client/commit/6e550260672507592d75c4781dc2563a50e664fa) Thanks [@ntucker](https://github.com/ntucker)! - BREAKING: new AbortOptimistic() -> [snapshot.abort](https://dataclient/docs/api/Snapshot#abort)

  #### Before

  ```ts
  getOptimisticResponse(snapshot, { id }) {
    const { data } = snapshot.getResponse(Base.get, { id });
    if (!data) throw new AbortOptimistic();
    return {
      id,
      votes: data.votes + 1,
    };
  }
  ```

  #### After

  ```ts
  getOptimisticResponse(snapshot, { id }) {
    const { data } = snapshot.getResponse(Base.get, { id });
    if (!data) throw snapshot.abort;
    return {
      id,
      votes: data.votes + 1,
    };
  }
  ```

- [#2921](https://github.com/reactive/data-client/pull/2921) [`6e55026`](https://github.com/reactive/data-client/commit/6e550260672507592d75c4781dc2563a50e664fa) Thanks [@ntucker](https://github.com/ntucker)! - BREAKING: new Query -> [new schema.Query](https://dataclient.io/rest/api/Query)

  #### Before

  ```jsx
  const getUserCount = new Query(
    new schema.All(User),
    (entries, { isAdmin } = {}) => {
      if (isAdmin !== undefined)
        return entries.filter(user => user.isAdmin === isAdmin).length;
      return entries.length;
    },
  );

  const userCount = useCache(getUserCount);
  const adminCount = useCache(getUserCount, { isAdmin: true });
  ```

  #### After

  ```jsx
  const getUserCount = new schema.Query(
    new schema.All(User),
    (entries, { isAdmin } = {}) => {
      if (isAdmin !== undefined)
        return entries.filter(user => user.isAdmin === isAdmin).length;
      return entries.length;
    },
  );

  const userCount = useQuery(getUserCount);
  const adminCount = useQuery(getUserCount, { isAdmin: true });
  ```

- [#2957](https://github.com/reactive/data-client/pull/2957) [`c129a25`](https://github.com/reactive/data-client/commit/c129a2558ecb21b5d9985c13747c555b88c51b3a) Thanks [@ntucker](https://github.com/ntucker)! - BREAKING CHANGE: Remove new AbortOptimistic() in favor of [snapshot.abort](https://dataclient.io/docs/api/Snapshot#abort)

  ```ts
  getOptimisticResponse(snapshot, { id }) {
    const { data } = snapshot.getResponse(Base.get, { id });
    if (!data) throw snapshot.abort;
    return {
      id,
      votes: data.votes + 1,
    };
  }
  ```

- [#2972](https://github.com/reactive/data-client/pull/2972) [`bb24601`](https://github.com/reactive/data-client/commit/bb24601e5ca5b0d92b8db75f115fcfb99fb97563) Thanks [@ntucker](https://github.com/ntucker)! - BREAKING: Entity.useIncoming → [Entity.shouldUpdate](https://dataclient.io/rest/api/Entity#shouldupdate))

  ```ts title="Before"
  class MyEntity extends Entity {
    // highlight-next-line
    static useIncoming(
      existingMeta: { date: number },
      incomingMeta: { date: number },
      existing: any,
      incoming: any,
    ) {
      return !deepEquals(existing, incoming);
    }
  }
  ```

  ```ts title="After"
  class MyEntity extends Entity {
    // highlight-next-line
    static shouldUpdate(
      existingMeta: { date: number },
      incomingMeta: { date: number },
      existing: any,
      incoming: any,
    ) {
      return !deepEquals(existing, incoming);
    }
  }
  ```

- [#2921](https://github.com/reactive/data-client/pull/2921) [`6e55026`](https://github.com/reactive/data-client/commit/6e550260672507592d75c4781dc2563a50e664fa) Thanks [@ntucker](https://github.com/ntucker)! - BREAKING: useCache(new Index(MyEntity)) -> useQuery(MyEntity)

  #### Before

  ```jsx
  const UserIndex = new Index(User);

  const bob = useCache(UserIndex, { username: 'bob' });
  ```

  #### After

  ```jsx
  const bob = useQuery(User, { username: 'bob' });
  ```

### Patch Changes

- [`2e169b7`](https://github.com/reactive/data-client/commit/2e169b705e4f8e2eea8005291a0e76e9d11764a4) Thanks [@ntucker](https://github.com/ntucker)! - Fix schema.All denormalize INVALID case should also work when class name mangling is performed in production builds
  - `unvisit()` always returns `undefined` with `undefined` as input.
  - `All` returns INVALID from `queryKey()` to invalidate what was previously a special case in `unvisit()` (when there is no table entry for the given entity)

- [#2962](https://github.com/reactive/data-client/pull/2962) [`f6f195d`](https://github.com/reactive/data-client/commit/f6f195d573c7c51dc63361a48b2ef804181a348b) Thanks [@ntucker](https://github.com/ntucker)! - Improve .extend() typing when using loose null checks and no body parameter

- [#2921](https://github.com/reactive/data-client/pull/2921) [`6e55026`](https://github.com/reactive/data-client/commit/6e550260672507592d75c4781dc2563a50e664fa) Thanks [@ntucker](https://github.com/ntucker)! - Update README

- [`8377e0a`](https://github.com/reactive/data-client/commit/8377e0a157419f0f4c237c392a895fec1772854d) Thanks [@ntucker](https://github.com/ntucker)! - fix: Resource.getList.schema args types

- [#2961](https://github.com/reactive/data-client/pull/2961) [`446f0b9`](https://github.com/reactive/data-client/commit/446f0b905f57c290e120c6f11a6b4708554283d1) Thanks [@ntucker](https://github.com/ntucker)! - Allow pk() to return numbers

  Before:

  ```ts
  class MyEntity extends Entity {
    id = 0;
    pk() {
      return `${this.id}`;
    }
  }
  ```

  After:

  ```ts
  class MyEntity extends Entity {
    id = 0;
    pk() {
      return this.id;
    }
  }
  ```

- Updated dependencies [[`2e169b7`](https://github.com/reactive/data-client/commit/2e169b705e4f8e2eea8005291a0e76e9d11764a4), [`6e55026`](https://github.com/reactive/data-client/commit/6e550260672507592d75c4781dc2563a50e664fa), [`6e55026`](https://github.com/reactive/data-client/commit/6e550260672507592d75c4781dc2563a50e664fa), [`73de27f`](https://github.com/reactive/data-client/commit/73de27fadb214c3c2995ca558daa9736312de7a9), [`59a407a`](https://github.com/reactive/data-client/commit/59a407a5bcaa8e5c6a948a85f5c52f106b24c5af), [`8377e0a`](https://github.com/reactive/data-client/commit/8377e0a157419f0f4c237c392a895fec1772854d), [`c129a25`](https://github.com/reactive/data-client/commit/c129a2558ecb21b5d9985c13747c555b88c51b3a), [`6e55026`](https://github.com/reactive/data-client/commit/6e550260672507592d75c4781dc2563a50e664fa), [`446f0b9`](https://github.com/reactive/data-client/commit/446f0b905f57c290e120c6f11a6b4708554283d1), [`bb24601`](https://github.com/reactive/data-client/commit/bb24601e5ca5b0d92b8db75f115fcfb99fb97563), [`6e55026`](https://github.com/reactive/data-client/commit/6e550260672507592d75c4781dc2563a50e664fa), [`446f0b9`](https://github.com/reactive/data-client/commit/446f0b905f57c290e120c6f11a6b4708554283d1), [`f68750f`](https://github.com/reactive/data-client/commit/f68750f8b0cafa66f6d50521e474db5e3d3c9cdd)]:
  - @data-client/endpoint@0.11.0

## 0.10.0

### Minor Changes

- [#2919](https://github.com/reactive/data-client/pull/2919) [`44f9ec2`](https://github.com/reactive/data-client/commit/44f9ec2801fe389a5afb215553a3441143078803) Thanks [@ntucker](https://github.com/ntucker)! - Add exports getUrlBase, getUrlTokens used to construct URLs

  This enables custom [RestEndpoint.url()](https://dataclient.io/rest/api/RestEndpoint#url) implementations

- [#2919](https://github.com/reactive/data-client/pull/2919) [`44f9ec2`](https://github.com/reactive/data-client/commit/44f9ec2801fe389a5afb215553a3441143078803) Thanks [@ntucker](https://github.com/ntucker)! - Add [RestEndpoint.searchToString()](https://dataclient.io/rest/api/RestEndpoint#searchToString)

  For example:

  To encode complex objects in the searchParams, you can use the [qs](https://github.com/ljharb/qs) library.

  ```typescript
  import { RestEndpoint, RestGenerics } from '@data-client/rest';
  import qs from 'qs';

  class MyEndpoint<O extends RestGenerics = any> extends RestEndpoint<O> {
    searchToString(searchParams) {
      return qs.stringify(searchParams);
    }
  }
  ```

### Patch Changes

- [`69834b5`](https://github.com/reactive/data-client/commit/69834b50c6d2b33f46d7c63cabdc0744abf160ae) Thanks [@ntucker](https://github.com/ntucker)! - Update README with API links

- Updated dependencies [[`922be79`](https://github.com/reactive/data-client/commit/922be79169a3eeea8e336eee519c165431ead474), [`69834b5`](https://github.com/reactive/data-client/commit/69834b50c6d2b33f46d7c63cabdc0744abf160ae), [`bf9c79c`](https://github.com/reactive/data-client/commit/bf9c79cb42e3df091eafe63fee619764a7ae4350)]:
  - @data-client/endpoint@0.10.0

## 0.9.9

### Patch Changes

- [`e3314a7`](https://github.com/reactive/data-client/commit/e3314a7ca64919c093b838048caaa8b7530fa7c8) Thanks [@ntucker](https://github.com/ntucker)! - docs: Add keywords to package

- Updated dependencies [[`e3314a7`](https://github.com/reactive/data-client/commit/e3314a7ca64919c093b838048caaa8b7530fa7c8)]:
  - @data-client/endpoint@0.9.9

## 0.9.8

### Patch Changes

- [#2837](https://github.com/reactive/data-client/pull/2837) [`57d87d6d85`](https://github.com/reactive/data-client/commit/57d87d6d851c19b4fd22eb57c629a7f2cab01f87) Thanks [@ntucker](https://github.com/ntucker)! - Query works with any Schema - including Collections

  ```ts
  export const queryRemainingTodos = new Query(
    TodoResource.getList.schema,
    entries => entries && entries.filter(todo => !todo.completed).length,
  );
  ```

  NOTE: Query.schema internals are laid out differently

- Updated dependencies [[`57d87d6d85`](https://github.com/reactive/data-client/commit/57d87d6d851c19b4fd22eb57c629a7f2cab01f87)]:
  - @data-client/endpoint@0.9.8

## 0.9.5

### Patch Changes

- [`bb4b9583c5`](https://github.com/reactive/data-client/commit/bb4b9583c52e2b2fe45765af10b385b571901ee7) Thanks [@ntucker](https://github.com/ntucker)! - docs: Update readme

## 0.9.4

### Patch Changes

- [`d1b51af7ac`](https://github.com/reactive/data-client/commit/d1b51af7ac4a8a7c0559f478cc9503be8e61514c) Thanks [@ntucker](https://github.com/ntucker)! - Fix unpkg bundles by ensuring dependencies are built in order

- Updated dependencies [[`d1b51af7ac`](https://github.com/reactive/data-client/commit/d1b51af7ac4a8a7c0559f478cc9503be8e61514c)]:
  - @data-client/endpoint@0.9.4

## 0.9.3

### Patch Changes

- [#2818](https://github.com/reactive/data-client/pull/2818) [`fc0092883f`](https://github.com/reactive/data-client/commit/fc0092883f5af42a5d270250482b7f0ba9845e95) Thanks [@ntucker](https://github.com/ntucker)! - Fix unpkg bundles and update names
  - Client packages namespace into RDC
    - @data-client/react - RDC
    - @data-client/core - RDC.Core
    - @data-client/redux - RDC.Redux
  - Definition packages namespace top level
    - @data-client/rest - Rest
    - @data-client/graphql - GraphQL
    - @data-client/img - Img
    - @data-client/endpoint - Endpoint
  - Utility
    - @data-client/normalizr - normalizr
    - @data-client/use-enhanced-reducer - EnhancedReducer

- Updated dependencies [[`fc0092883f`](https://github.com/reactive/data-client/commit/fc0092883f5af42a5d270250482b7f0ba9845e95)]:
  - @data-client/endpoint@0.9.3

## 0.9.2

### Patch Changes

- [`4ea0bc83f6`](https://github.com/reactive/data-client/commit/4ea0bc83f65f49cb2155f6aecdc5f8d1b168fd5e) Thanks [@ntucker](https://github.com/ntucker)! - Docs: Update repo links to reactive organization

- Updated dependencies [[`4ea0bc83f6`](https://github.com/reactive/data-client/commit/4ea0bc83f65f49cb2155f6aecdc5f8d1b168fd5e)]:
  - @data-client/endpoint@0.9.2

## 0.9.0

### Patch Changes

- Updated dependencies [[`386372ed4d`](https://github.com/reactive/data-client/commit/386372ed4d0b454687847ba2b8eed4369ef7cdf7)]:
  - @data-client/endpoint@0.9.0

## 0.8.2

### Patch Changes

- [`664d3eacff`](https://github.com/reactive/data-client/commit/664d3eacff08c3c75e8ed7c3ccc64ee21faa6f7f) Thanks [@ntucker](https://github.com/ntucker)! - Remove dev warning for old versions of client

- [#2799](https://github.com/reactive/data-client/pull/2799) [`26a3843d1b`](https://github.com/reactive/data-client/commit/26a3843d1b61900c385d8626d7062d6f0424c137) Thanks [@ntucker](https://github.com/ntucker)! - Removed some forms of automatic entity validation
  - Now allow missing schemas making it easier to declare partials
  - Removed logic for certain keys found out of defaults

  We are generally trying to be more lax and focus on catching
  clearly wrong signals. A lot of help comes from network response
  form detection.

- Updated dependencies [[`664d3eacff`](https://github.com/reactive/data-client/commit/664d3eacff08c3c75e8ed7c3ccc64ee21faa6f7f), [`26a3843d1b`](https://github.com/reactive/data-client/commit/26a3843d1b61900c385d8626d7062d6f0424c137)]:
  - @data-client/endpoint@0.8.2

## 0.8.1

### Patch Changes

- [#2797](https://github.com/reactive/data-client/pull/2797) [`c6ee872c7d`](https://github.com/reactive/data-client/commit/c6ee872c7d4bb669fa7b08a5343b24419c797cee) Thanks [@ntucker](https://github.com/ntucker)! - Fix published dependency range

## 0.8.0

### Minor Changes

- [`f65cf832f0`](https://github.com/reactive/data-client/commit/f65cf832f0cdc4d01cb2f389a2dc2b37f1e5cf04) Thanks [@ntucker](https://github.com/ntucker)! - BREAKING: Remove all /next exports

- [#2790](https://github.com/reactive/data-client/pull/2790) [`3f36f56939`](https://github.com/reactive/data-client/commit/3f36f5693961fe2c38af172fe192bd57bda488cb) Thanks [@ntucker](https://github.com/ntucker)! - Remove support for non-Collection [pagination](https://dataclient.io/rest/guides/pagination)

  BREAKING CHANGE: [RestEndpoint](https://dataclient.io/rest/api/RestEndpoint) with Arrays no longer support [.paginated()](https://dataclient.io/rest/api/RestEndpoint#paginated)

- [#2789](https://github.com/reactive/data-client/pull/2789) [`440d415bc8`](https://github.com/reactive/data-client/commit/440d415bc81f1d44db2f192ff9634d2144403c61) Thanks [@ntucker](https://github.com/ntucker)! - getPage,push,unshift,assign should not match name of parent

  ```ts
  const getTodos = new RestEndpoint({
    urlPrefix: 'https://jsonplaceholder.typicode.com',
    path: '/todos',
    schema: new schema.Collection([Todo]),
    name: 'gettodos',
  });

  getTodos.getPage.name === 'gettodos.getPage';
  getTodos.push.name === 'gettodos.create';
  getTodos.unshift.name === 'gettodos.create';
  ```

- [#2795](https://github.com/reactive/data-client/pull/2795) [`79e286109b`](https://github.com/reactive/data-client/commit/79e286109b5566f8e7acfdf0f44201263072d1d1) Thanks [@ntucker](https://github.com/ntucker)! - BREAKING: [Schema Serializers](https://dataclient.io/rest/guides/network-transform#deserializing-fields) _must_ support function calls

  This means Date will no longer work like before. Possible migrations:

  ```ts
  class Ticker extends Entity {
    trade_id = 0;
    price = 0;
    time = Temporal.Instant.fromEpochSeconds(0);

    pk(): string {
      return `${this.trade_id}`;
    }
    static key = 'Ticker';

    static schema = {
      price: Number,
      time: Temporal.Instant.from,
    };
  }
  ```

  or to continue using Date:

  ```ts
  class Ticker extends Entity {
    trade_id = 0;
    price = 0;
    time = Temporal.Instant.fromEpochSeconds(0);

    pk(): string {
      return `${this.trade_id}`;
    }
    static key = 'Ticker';

    static schema = {
      price: Number,
      time: (iso: string) => new Date(iso),
    };
  }
  ```

### Patch Changes

- [#2779](https://github.com/reactive/data-client/pull/2779) [`ff51e71f45`](https://github.com/reactive/data-client/commit/ff51e71f45857eb172f3fe05829e34c9abb68252) Thanks [@ntucker](https://github.com/ntucker)! - Update jsdocs references to dataclient.io

- Updated dependencies [[`ff51e71f45`](https://github.com/reactive/data-client/commit/ff51e71f45857eb172f3fe05829e34c9abb68252), [`c535f6c0ac`](https://github.com/reactive/data-client/commit/c535f6c0ac915b5242c1c7694308b7ee7aab16a1), [`79e286109b`](https://github.com/reactive/data-client/commit/79e286109b5566f8e7acfdf0f44201263072d1d1)]:
  - @data-client/endpoint@0.8.0

## 0.7.6

### Patch Changes

- 8d9f6fe15c: fix: Export types needed for Resource.extend

  ```
  cannot be named without a reference to '../../node_modules/@data-client/rest/lib/resourceExtensionTypes'. This is likely not portable. A type annotation is necessary.ts(2742)
  ```

- a8936f5e6d: Entity.process() now gets an addition argument of 'args' (sent from endpoint)

  ```ts
  class Stream extends Entity {
    username = '';
    title = '';
    game = '';
    currentViewers = 0;
    live = false;

    pk() {
      return this.username;
    }
    static key = 'Stream';

    process(value, parent, key, args) {
      const processed = super.process(value, parent, key, args);
      processed.username = args[0]?.username;
      return processed;
    }
  }
  ```

- Updated dependencies [a8936f5e6d]
  - @data-client/endpoint@0.2.8

## 0.7.5

### Patch Changes

- b60a4a558e: Change internal organization of some types
- Updated dependencies [b60a4a558e]
  - @data-client/endpoint@0.2.7

## 0.7.4

### Patch Changes

- 7436b43f78: Fix Resource.extend() for builtin endpoints with zero typing options

  ```ts
  const RatingResource = createResource({
    path: '/ratings/:id',
    schema: Rating,
  }).extend({
    getList: {
      dataExpiryLength: 10 * 60 * 1000, // 10 minutes
    },
  });
  ```

  This would previously break the types of RatingResource.getList.
  This would only occur because dataExpiryLength is not a type-influencing option.

## 0.7.3

### Patch Changes

- e934b53551: Add [Collection](https://dataclient.io/rest/api/createResource#collection) option to [createResource](https://dataclient.io/rest/api/createResource)

## 0.7.2

### Patch Changes

- 318df89bf7: Add nonFilterArgumentKeys argument to Collection

  `nonFilterArgumentKeys` defines a test to determine which argument keys
  are not used for filtering the results. For instance, if your API uses
  'orderBy' to choose a sort - this argument would not influence which
  entities are included in the response.

  This allows customizing `createCollectionFilter` for the
  most common case

- Updated dependencies [318df89bf7]
- Updated dependencies [1fcaeb1a7b]
  - @data-client/endpoint@0.2.6

## 0.7.1

### Patch Changes

- 4317adb94c: Collection based pagination now replaces the non-list members on page

  This allows members like nextPage or 'cursor' to be updated when
  each page is fetched making it easier to know which page to fetch next.

- Updated dependencies [5a16f86668]
- Updated dependencies [4317adb94c]
  - @data-client/endpoint@0.2.5

## 0.7.0

### Minor Changes

- c8c5575e5a: Add 'paginationField' parameter to [RestEndpoint](https://dataclient.io/rest/api/RestEndpoint#paginationfield) and [createResource](https://dataclient.io/rest/api/createResource#paginationfield)

  This adds a '[getPage](https://dataclient.io/rest/api/RestEndpoint#getPage)' member; similar to getList.push/unshift but for [pagination](https://dataclient.io/rest/guides/pagination).

  ```ts
  const TodoResource = createResource({
    path: '/todos/:id',
    schema: Todo,
    paginationField: 'page',
  }).getList.getPage({ page: '2' });
  ```

### Patch Changes

- c8c5575e5a: Fix case where sometimes paginating would not update a collection

  This was due to the comparison not using string serialization (canonical form for collection comparisons)

- c8c5575e5a: Ignore 'undefined' parameters in collection matching
- Updated dependencies [c8c5575e5a]
- Updated dependencies [4e9d34ebc1]
  - @data-client/endpoint@0.2.4

## 0.6.0

### Minor Changes

- af8b76079f: Support FormData in Resource updates and creates

## 0.5.0

### Minor Changes

- 51b4b0d188: Deprecate Resource.create
- 51b4b0d188: Add Resource.extend()

  This is polymorphic, and has three forms

  Set any field based on arguments:

  ```ts
  Resource.extend('fieldName', { path: 'mypath/:id' });
  ```

  Override any of the provided endpoints with options:

  ```ts
  Resource.extend({
    getList: {
      path: 'mypath/:id',
    },
    update: {
      body: {} as Other,
    },
  });
  ```

  Function to compute derived endpoints:

  ```ts
  Resource.extend(base => ({
    getByComment: base.getList.extend({
      path: 'repos/:owner/:repo/issues/comments/:comment/reactions',
    }),
  }));
  ```

  Idea credits: @Dav3rs

- 51b4b0d188: Remove createResource pagination field in favor of getList.paginated

### Patch Changes

- 51b4b0d188: Fix endpoint.push/unshift/assign method type

## 0.4.1

### Patch Changes

- 6e790725ae: Add more docstrings to RestEndpoint members
- 27274bcf21: Allow DELETE to have body if specified

## 0.4.0

### Minor Changes

- 8a71700644: push/unshift/assign inherit body type

### Patch Changes

- 8a71700644: scheam.push/unshift type denormalize to singular item (for now)
- 8a71700644: fix: Support Collections with boolean parameters
- Updated dependencies [8a71700644]
- Updated dependencies [8a71700644]
- Updated dependencies [8a71700644]
  - @data-client/endpoint@0.2.3

## 0.3.1

### Patch Changes

- 7b835f113a: Improve package tags
- 8af1b5a8ef: Detect unusable pk when pk is serialized
- Updated dependencies [f4b625df5a]
- Updated dependencies [8af1b5a8ef]
- Updated dependencies [6f3b39b585]
  - @data-client/endpoint@0.2.2

## 0.3.0

### Minor Changes

- ab9c805a6c: Add createResource() paginationField argument
  When supplied, will enable Resource.getNextPage

### Patch Changes

- 1efd401bef: fix(types): RestEndpoint.push/unshift/assign return type is no longer nested Promises
- 12c2596453: fix: Ensure Entit.key can be set in v8 browsers
- 1efd401bef: enhance: createResource() throws with path not containing any :path
- Updated dependencies [69ce1f8b6b]
- Updated dependencies [12c2596453]
- Updated dependencies [6c8f0be900]
  - @data-client/endpoint@0.2.1

## 0.2.0

### Minor Changes

BREAKING: Calling super.getRequestInit() will return a promise - so you must resolve it:

```ts
class AuthdEndpoint<O extends RestGenerics = any> extends RestEndpoint<O> {
  getRequestInit(body: any): RequestInit {
    return {
      ...super.getRequestInit(body),
      credentials: 'same-origin',
    };
  }
}
```

->

```ts
class AuthdEndpoint<O extends RestGenerics = any> extends RestEndpoint<O> {
  async getRequestInit(body: any): Promise<RequestInit> {
    return {
      ...(await super.getRequestInit(body)),
      credentials: 'same-origin',
    };
  }
}
```

- bf141cb5a5: Removed deprecated Endpoint.optimisticUpdate -> use Endpoint.getOptimisticResponse
- 9788090c55: RestEndpoint's getRequestInit and getHeaders optionally return a promise
- 9788090c55: GetEndpoint and MutateEndpoint parameters changed to what NewXEndpoint was.
- 9788090c55: createResource() generics changed to O extends ResourceGenerics
  This allows customizing the Resource type with body and searchParams
- 9788090c55: createResource().getList uses a Collection, which .create appends to
  Remove any Endpoint.update as it is not necessary and will not work
- 011cc20732: Remove FetchShape compatibility.
  This removes support for the legacy hooks in 'rest-hooks' like useResource()

### Patch Changes

- 9788090c55: Fix Collection creates (like push, unshift) normalizing when no collections are in store
- 9788090c55: Fix Collections handling single item with Union schema
- Updated dependencies [bf141cb5a5]
- Updated dependencies [9788090c55]
- Updated dependencies [9788090c55]
- Updated dependencies [011cc20732]
  - @data-client/endpoint@0.2.0
