From d0bfa073e7b0e027cc091d9fa0118d88b30a0c50 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Oct 2026 04:51:14 +0000 Subject: [PATCH] internal: Publish new version --- .changeset/agent-skills-in-packages.md | 18 - .changeset/babel-runtime-8.md | 16 - .changeset/codemods-package.md | 11 - .changeset/controller-set-array.md | 30 -- .changeset/controller-set-invalidate.md | 21 - .changeset/controller-set-value-types.md | 32 -- .changeset/controller-subclass-option.md | 24 - .changeset/core-mock-fixture-types.md | 12 - .changeset/data-client-router-skill.md | 7 - .changeset/deleted-entity-undefined.md | 23 - .changeset/devtools-action-log.md | 18 - .changeset/devtools-date-format-perf.md | 12 - .changeset/devtools-unique-controller-keys.md | 11 - .changeset/drop-typescript-3.md | 19 - .changeset/entity-pk-readonly-args.md | 27 -- .changeset/extend-process-params.md | 26 - .changeset/faster-rest-types.md | 23 - .changeset/fetch-meta-promise.md | 24 - .changeset/fixture-args-readonly.md | 25 - .changeset/legacy-ts-endpoint-libcheck.md | 30 -- .changeset/legacy-ts-inline-type-imports.md | 21 - .changeset/legacy-ts-noinfer.md | 22 - .changeset/manager-middleware-required.md | 18 - .changeset/manager-without-middleware.md | 11 - .changeset/max-entity-depth-jsdoc.md | 9 - .changeset/native-focus-refetch.md | 13 - .changeset/optimistic-response-types.md | 31 -- .changeset/prepare-store-redux-store.md | 23 - .changeset/query-collection-push-body.md | 27 -- .changeset/react-native-087.md | 7 - .../render-data-hook-suspend-effects.md | 7 - .changeset/resource-create-formdata.md | 21 - .changeset/resource-extend-keeps-members.md | 17 - .changeset/rest-array-body-json.md | 21 - .changeset/test-mock-reexports.md | 17 - .changeset/test-renderhook-ts4.md | 16 - .changeset/test-rntl-14.md | 7 - .changeset/typescript7-exports.md | 15 - .changeset/vue-create-data-client-internal.md | 15 - .changeset/vue-default-gcpolicy.md | 25 - .../vue-deprecate-wait-for-next-update.md | 48 -- .changeset/vue-expiry-stable.md | 19 - .changeset/vue-export-gcpolicy.md | 16 - .changeset/vue-getter-args.md | 19 - .changeset/vue-internal-exports.md | 7 - .changeset/vue-plugin-onunmount.md | 12 - .changeset/vue-stale-refetch.md | 17 - .changeset/vue-suspense-arg-errors.md | 19 - .changeset/vue-suspense-keep-previous.md | 15 - .../vue-suspense-stale-while-revalidate.md | 10 - .changeset/vue-usefetch-gc.md | 5 - .changeset/vue-usefetch-ref-type.md | 16 - examples/benchmark-react/CHANGELOG.md | 10 + examples/benchmark-react/package.json | 2 +- examples/benchmark/CHANGELOG.md | 9 + examples/benchmark/package.json | 2 +- examples/coin-app/CHANGELOG.md | 9 + examples/coin-app/package.json | 8 +- examples/normalizr-github/CHANGELOG.md | 8 + examples/normalizr-github/package.json | 2 +- examples/normalizr-redux/CHANGELOG.md | 8 + examples/normalizr-redux/package.json | 2 +- examples/normalizr-relationships/CHANGELOG.md | 8 + examples/normalizr-relationships/package.json | 2 +- examples/test-bundlesize/CHANGELOG.md | 9 + examples/test-bundlesize/package.json | 2 +- packages/codemods/CHANGELOG.md | 13 + packages/codemods/package.json | 2 +- packages/core/CHANGELOG.md | 239 +++++++++ packages/core/package.json | 2 +- packages/endpoint/CHANGELOG.md | 143 ++++++ packages/endpoint/package.json | 2 +- packages/graphql/CHANGELOG.md | 146 ++++++ packages/graphql/package.json | 2 +- packages/img/CHANGELOG.md | 28 ++ packages/img/package.json | 4 +- packages/normalizr/CHANGELOG.md | 62 +++ packages/normalizr/package.json | 2 +- packages/react/CHANGELOG.md | 300 ++++++++++++ packages/react/package.json | 2 +- packages/rest/CHANGELOG.md | 231 +++++++++ packages/rest/package.json | 2 +- packages/test/CHANGELOG.md | 122 +++++ packages/test/package.json | 4 +- packages/use-enhanced-reducer/CHANGELOG.md | 8 + packages/use-enhanced-reducer/package.json | 2 +- packages/vue/CHANGELOG.md | 452 ++++++++++++++++++ packages/vue/package.json | 2 +- yarn.lock | 26 +- 89 files changed, 1846 insertions(+), 986 deletions(-) delete mode 100644 .changeset/agent-skills-in-packages.md delete mode 100644 .changeset/babel-runtime-8.md delete mode 100644 .changeset/codemods-package.md delete mode 100644 .changeset/controller-set-array.md delete mode 100644 .changeset/controller-set-invalidate.md delete mode 100644 .changeset/controller-set-value-types.md delete mode 100644 .changeset/controller-subclass-option.md delete mode 100644 .changeset/core-mock-fixture-types.md delete mode 100644 .changeset/data-client-router-skill.md delete mode 100644 .changeset/deleted-entity-undefined.md delete mode 100644 .changeset/devtools-action-log.md delete mode 100644 .changeset/devtools-date-format-perf.md delete mode 100644 .changeset/devtools-unique-controller-keys.md delete mode 100644 .changeset/drop-typescript-3.md delete mode 100644 .changeset/entity-pk-readonly-args.md delete mode 100644 .changeset/extend-process-params.md delete mode 100644 .changeset/faster-rest-types.md delete mode 100644 .changeset/fetch-meta-promise.md delete mode 100644 .changeset/fixture-args-readonly.md delete mode 100644 .changeset/legacy-ts-endpoint-libcheck.md delete mode 100644 .changeset/legacy-ts-inline-type-imports.md delete mode 100644 .changeset/legacy-ts-noinfer.md delete mode 100644 .changeset/manager-middleware-required.md delete mode 100644 .changeset/manager-without-middleware.md delete mode 100644 .changeset/max-entity-depth-jsdoc.md delete mode 100644 .changeset/native-focus-refetch.md delete mode 100644 .changeset/optimistic-response-types.md delete mode 100644 .changeset/prepare-store-redux-store.md delete mode 100644 .changeset/query-collection-push-body.md delete mode 100644 .changeset/react-native-087.md delete mode 100644 .changeset/render-data-hook-suspend-effects.md delete mode 100644 .changeset/resource-create-formdata.md delete mode 100644 .changeset/resource-extend-keeps-members.md delete mode 100644 .changeset/rest-array-body-json.md delete mode 100644 .changeset/test-mock-reexports.md delete mode 100644 .changeset/test-renderhook-ts4.md delete mode 100644 .changeset/test-rntl-14.md delete mode 100644 .changeset/typescript7-exports.md delete mode 100644 .changeset/vue-create-data-client-internal.md delete mode 100644 .changeset/vue-default-gcpolicy.md delete mode 100644 .changeset/vue-deprecate-wait-for-next-update.md delete mode 100644 .changeset/vue-expiry-stable.md delete mode 100644 .changeset/vue-export-gcpolicy.md delete mode 100644 .changeset/vue-getter-args.md delete mode 100644 .changeset/vue-internal-exports.md delete mode 100644 .changeset/vue-plugin-onunmount.md delete mode 100644 .changeset/vue-stale-refetch.md delete mode 100644 .changeset/vue-suspense-arg-errors.md delete mode 100644 .changeset/vue-suspense-keep-previous.md delete mode 100644 .changeset/vue-suspense-stale-while-revalidate.md delete mode 100644 .changeset/vue-usefetch-gc.md delete mode 100644 .changeset/vue-usefetch-ref-type.md create mode 100644 packages/codemods/CHANGELOG.md diff --git a/.changeset/agent-skills-in-packages.md b/.changeset/agent-skills-in-packages.md deleted file mode 100644 index aff1a540f785..000000000000 --- a/.changeset/agent-skills-in-packages.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/endpoint': patch -'@data-client/graphql': patch -'@data-client/react': patch -'@data-client/rest': patch -'@data-client/vue': patch ---- - -Ship agent skills inside the packages - -Coding agents can now follow the skills for the version you have installed instead of guessing from older releases. Each package carries the skills it covers, and the new `data-client-skills` command (in `@data-client/react`, `vue`, `rest`, `graphql` and `endpoint`, so repos with only API definitions get it too) links them into `.agents/skills`, with `.claude/skills` linking to it, where Claude Code, Cursor and Codex load them as their own: - -```bash -npx --no data-client-skills -``` - -Commit the links. They point into `node_modules`, so they follow upgrades; run it again after adding, removing or upgrading `@data-client` packages to pick up new skills. [TanStack Intent](https://tanstack.com/intent) also finds these skills. diff --git a/.changeset/babel-runtime-8.md b/.changeset/babel-runtime-8.md deleted file mode 100644 index 20e66ed1f053..000000000000 --- a/.changeset/babel-runtime-8.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/endpoint': patch -'@data-client/graphql': patch -'@data-client/img': patch -'@data-client/normalizr': patch -'@data-client/react': patch -'@data-client/rest': patch -'@data-client/test': patch -'@data-client/use-enhanced-reducer': patch -'@data-client/vue': patch ---- - -Support `@babel/runtime` 8 - -Apps on Babel 8 now share their `@babel/runtime` with Data Client instead of installing a second copy. Apps on Babel 7 keep working unchanged. diff --git a/.changeset/codemods-package.md b/.changeset/codemods-package.md deleted file mode 100644 index 6912b25380bb..000000000000 --- a/.changeset/codemods-package.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@data-client/codemods': minor ---- - -New package: run Data Client codemods with `npx @data-client/codemods ` - -The codemods ship on npm with each release, instead of being fetched from dataclient.io at run time. - -```bash -npx @data-client/codemods v0.18 src/ -``` diff --git a/.changeset/controller-set-array.md b/.changeset/controller-set-array.md deleted file mode 100644 index ad90f6bf28df..000000000000 --- a/.changeset/controller-set-array.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/react': patch -'@data-client/vue': patch -'@data-client/normalizr': patch ---- - -Fix `controller.set()` types for Array schemas - -`controller.set([Entity], rows)` and `controller.set(new schema.Array(Entity), rows)` now typecheck. This writes every row in one store update: each row merges with its stored entity, and entities not in `rows` stay. This works with `exactOptionalPropertyTypes` on too. - -Rows are typed by the Entity's fields. The schema holds one Entity, [Union](https://dataclient.io/rest/api/Union) (for mixed types) or [Invalidate](https://dataclient.io/rest/api/Invalidate) (to delete), in an Array or [Values](https://dataclient.io/rest/api/Values) (which takes an object keyed by id). - -Batch `set()` needs `@data-client/rest` (or `endpoint`/`graphql`) from this release, since older Entity classes don't type as `EntityInterface`. - -```ts -// Before: TypeScript error on [Ticker], so batches became one set() per row -for (const row of rows) { - ctrl.set(Ticker, { product_id: row.product_id }, row); -} - -// After: one store update -ctrl.set([Ticker], rows); - -// Mixed Entity types, batch deletes, and rows keyed by id -const Message = new schema.Union({ ticker: Ticker, trade: Trade }, 'type'); -ctrl.set([Message], messages); -ctrl.set([new schema.Invalidate(Ticker)], [{ product_id: 'BTC-USD' }]); -ctrl.set(new schema.Values(Ticker), { 'BTC-USD': row }); -``` diff --git a/.changeset/controller-set-invalidate.md b/.changeset/controller-set-invalidate.md deleted file mode 100644 index 4760c39ecf33..000000000000 --- a/.changeset/controller-set-invalidate.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/react': patch -'@data-client/vue': patch ---- - -Fix `controller.set()` types for a single [Invalidate](https://dataclient.io/rest/api/Invalidate) - -Deleting one entity with `set()` worked at runtime but failed to typecheck, since `Invalidate` isn't -[Queryable](https://dataclient.io/rest/api/schema#queryable). Pass the schema and the row to delete; the row is typed -by the Entity's fields. - -```ts -// Before: TypeScript error, so a one-row batch was the workaround -ctrl.set([new Invalidate(Post)], [{ id: '5' }]); - -// After -ctrl.set(new Invalidate(Post), { id: '5' }); -``` - -Like batch `set()`, it takes no `args` and no updater function. diff --git a/.changeset/controller-set-value-types.md b/.changeset/controller-set-value-types.md deleted file mode 100644 index 7c01084d073a..000000000000 --- a/.changeset/controller-set-value-types.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/react': patch -'@data-client/vue': patch ---- - -Fix `controller.set()` accepting any value - -Values are now typed by the schema: Entities take their fields, while [Collection](https://dataclient.io/rest/api/Collection) -and [All](https://dataclient.io/rest/api/All) take a list of rows. [Query](https://dataclient.io/rest/api/Query) takes -the input of the schema it wraps, not what its `process()` returns. Updater functions must return the same. - -```ts -// Before: these all typechecked, then failed or wrote nothing at runtime -ctrl.set(new schema.All(Todo), 42); -ctrl.set(TodoResource.getList.schema, 'anything'); -ctrl.set(Todo, { id: '5' }, { id: '5', completed: 'yes' }); - -// After: TypeScript errors on the above; these typecheck -ctrl.set(TodoResource.getList.schema, [{ id: '5', completed: true }]); -ctrl.set(new schema.All(Todo), [{ id: '5', completed: true }]); -``` - -When each member declares its discriminator as a literal (like `readonly type = 'post'`), a -[Union](https://dataclient.io/rest/api/Union) row is checked against the member it selects. Only -declared fields are accepted, so a key read by a `schemaAttribute` function must be declared on each member. - -```ts -const Feed = new schema.Union({ post: Post, comment: Comment }, 'type'); -// TypeScript error: commentBody is a Comment field, not a Post field -ctrl.set(Feed, { id: '1', type: 'post' }, { type: 'post', commentBody: 'hi' }); -``` diff --git a/.changeset/controller-subclass-option.md b/.changeset/controller-subclass-option.md deleted file mode 100644 index dc29a3f7aac7..000000000000 --- a/.changeset/controller-subclass-option.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/react': patch -'@data-client/vue': patch -'@data-client/test': patch ---- - -Fix TypeScript error passing a `Controller` subclass to `DataProvider` or `DataClientPlugin` - -A plain `class MyController extends Controller` failed to typecheck as the `Controller` option of [DataProvider](https://dataclient.io/docs/api/DataProvider#Controller), Vue's [DataClientPlugin](https://dataclient.io/vue/api/DataClientPlugin#Controller), and the `@data-client/react/redux` `DataProvider`, so the documented example needed a cast. `MockController()` from `@data-client/core/mock` had the same error when wrapping your subclass. These now typecheck, and you can drop the casts. - -```tsx -class MyController extends Controller { - doSomething = () => console.log('hi'); -} - -// Before: TypeScript error, so you had to cast - -app.use(DataClientPlugin, { Controller: MyController as typeof Controller }); - -// After - -app.use(DataClientPlugin, { Controller: MyController }); -``` diff --git a/.changeset/core-mock-fixture-types.md b/.changeset/core-mock-fixture-types.md deleted file mode 100644 index 899f55ced5ff..000000000000 --- a/.changeset/core-mock-fixture-types.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/react': patch -'@data-client/test': patch ---- - -Fix fixture types needing `@data-client/endpoint` installed - -`Fixture` and the other fixture types from `@data-client/react/mock`, `@data-client/core/mock` and `@data-client/test` no -longer resolve `@data-client/endpoint`, which those packages don't depend on. Projects that install only -`@data-client/react` and `@data-client/test` (for example with pnpm's strict layout) no longer get -`Cannot find module '@data-client/endpoint'` when type-checking fixtures. diff --git a/.changeset/data-client-router-skill.md b/.changeset/data-client-router-skill.md deleted file mode 100644 index d61b00b2c9c0..000000000000 --- a/.changeset/data-client-router-skill.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@data-client/core': patch ---- - -Ship a `data-client` agent skill that routes "use Data Client" to setup - -Asking your coding agent to use Data Client in an app without it now reaches the setup skill, which installs the packages and adds the provider. In apps that have it, the skill points your agent at the skill for the task. diff --git a/.changeset/deleted-entity-undefined.md b/.changeset/deleted-entity-undefined.md deleted file mode 100644 index d3d19a19a87b..000000000000 --- a/.changeset/deleted-entity-undefined.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/react': patch -'@data-client/vue': patch ---- - -Fix `useCache()` and `useDLE()` returning a truthy `Symbol` for deleted entities - -After an entity was deleted and its refetch failed, `useCache()` and `useDLE()` (React and Vue) returned an internal -`Symbol` instead of `undefined`. Since a `Symbol` is truthy, "not loaded" checks passed, and code went on to use it as -the entity: - -```tsx -const todo = useCache(TodoResource.get, { id }); -if (!todo) return ; -// Before: reached here with a Symbol; todo.title was undefined and todo.title.trim() threw -// After: the placeholder renders -return ; -``` - -[Controller.getResponse()](https://dataclient.io/docs/api/Controller#getResponse) and -[Controller.fetchIfStale()](https://dataclient.io/docs/api/Controller#fetchIfStale) now also give `undefined` there, -like [Controller.get()](https://dataclient.io/docs/api/Controller#get) already did. diff --git a/.changeset/devtools-action-log.md b/.changeset/devtools-action-log.md deleted file mode 100644 index fc20d7689625..000000000000 --- a/.changeset/devtools-action-log.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/react': patch -'@data-client/vue': patch ---- - -Add recent actions to `globalThis.__DC_ACTIONS__` in development - -Coding agents and console debugging can now see what each store dispatched, including the fetches made while the -page loaded, without the Redux DevTools extension. [DevToolsManager](https://dataclient.io/docs/api/DevToolsManager#controllers) -keeps each store's recent actions in a `Map` keyed like `__DC_CONTROLLERS__`. Production builds don't include it. - -To keep memory small, only the newest 20 actions keep their payloads, and each polling key (endpoint and args) keeps -only its last two polls (`maxPollingActions`, default 4 actions). - -```js title="Browser DevTools console" -__DC_ACTIONS__.get('Data Client: My App').slice(-10); -``` diff --git a/.changeset/devtools-date-format-perf.md b/.changeset/devtools-date-format-perf.md deleted file mode 100644 index 056402c07d9b..000000000000 --- a/.changeset/devtools-date-format-perf.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/react': patch -'@data-client/vue': patch ---- - -Fix slow updates in development while Redux DevTools is open - -With the [Redux DevTools](https://dataclient.io/docs/getting-started/debugging) extension open, every store update -stalled the page while DevTools serialized the store: about 20ms with 50 entities, and 200ms with 500. Apps doing -many `controller.set()` calls, polling, or live updates would stutter in development. Each update now serializes -40-60x faster, and timestamps still show as readable times like `10:42:07.123 AM`. diff --git a/.changeset/devtools-unique-controller-keys.md b/.changeset/devtools-unique-controller-keys.md deleted file mode 100644 index 00b36258239a..000000000000 --- a/.changeset/devtools-unique-controller-keys.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/react': patch -'@data-client/vue': patch ---- - -Fix stores with the same devtools name hiding each other in `__DC_CONTROLLERS__` - -With two `DataProvider`s, or two Vue apps using `DataClientPlugin`, on one page and the default devtools name, the -second store replaced the first in `globalThis.__DC_CONTROLLERS__`, so debugging tools and coding agents could only find one. The second now -registers as `'Data Client: My App (2)'`, the next as `(3)`, and so on. diff --git a/.changeset/drop-typescript-3.md b/.changeset/drop-typescript-3.md deleted file mode 100644 index c35770a331bd..000000000000 --- a/.changeset/drop-typescript-3.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@data-client/core': minor -'@data-client/endpoint': minor -'@data-client/normalizr': minor -'@data-client/react': minor -'@data-client/graphql': minor -'@data-client/img': minor -'@data-client/test': minor ---- - -BREAKING: Require TypeScript 4.0 or later - -The TypeScript 3.x type declarations are removed. They no longer type-checked on any TypeScript 3.x version, and -`@data-client/rest` already required TypeScript 4.0. Upgrade TypeScript to 4.0 or later. - -```diff title="package.json" -- "typescript": "^3.9.0" -+ "typescript": "^4.0.0" -``` diff --git a/.changeset/entity-pk-readonly-args.md b/.changeset/entity-pk-readonly-args.md deleted file mode 100644 index 6cd0e9e187fc..000000000000 --- a/.changeset/entity-pk-readonly-args.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -'@data-client/endpoint': patch -'@data-client/rest': patch -'@data-client/graphql': patch ---- - -Fix Entity classes not assignable to `EntityInterface` - -[Entity.pk()](https://dataclient.io/rest/api/Entity#pk)'s static `args` parameter is now `readonly any[]`, matching `EntityInterface`. Entity classes can be passed where an `EntityInterface` is expected. - -```ts -import type { EntityInterface } from '@data-client/react'; - -// Before: TypeScript error (args is readonly in EntityInterface) -// After: typechecks -const schema: EntityInterface = User; -``` - -Overrides of `static pk()` that type `args` as a mutable array still compile, but a future breaking release will require `readonly any[]`, so update them now: - -```ts -class User extends Entity { - static pk(value: any, parent?: any, key?: string, args?: readonly any[]) { - return `${value.id}-${args?.[0]?.org}`; - } -} -``` diff --git a/.changeset/extend-process-params.md b/.changeset/extend-process-params.md deleted file mode 100644 index 29b6af3714db..000000000000 --- a/.changeset/extend-process-params.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -'@data-client/rest': patch ---- - -Type the `params` and `body` that `process()` receives in `RestEndpoint` options - -A `process(value, params)` method passed to `new RestEndpoint()`, `RestEndpoint.extend()` or `resource().extend()` used to get `params` typed as `any`, so a typo or a wrong assumption about a path parameter went unnoticed until runtime. They are now typed from the endpoint's `path`, `searchParams` and `body`, including a `path` set in the same `.extend()` call. - -```ts -const getUser = new RestEndpoint({ path: '/users/:id' }); - -const getUserById = getUser.extend({ - path: '/users/by-id/:userId', - process(value, params) { - params.userId; // string | number - params.id; // TypeScript error: 'id' is not a param of '/users/by-id/:userId' - return value; - }, -}); -``` - -Endpoints whose params are optional pass `params` as possibly `undefined`, so read it with `params?.page`. - -This can surface new TypeScript errors in existing `process()` methods that read a param the endpoint doesn't have, or that read optional `params` without a check. Each is a read that could be `undefined` or throw at runtime, so fix the param name or add the check. - -On TypeScript 5.x and earlier, `process(value, params)` in an `.extend()` that also sets `path` no longer fails with "implicitly has an 'any' type" under `strict`. diff --git a/.changeset/faster-rest-types.md b/.changeset/faster-rest-types.md deleted file mode 100644 index 48743f15d640..000000000000 --- a/.changeset/faster-rest-types.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -'@data-client/rest': patch -'@data-client/endpoint': patch -'@data-client/graphql': patch ---- - -Speed up TypeScript checking of `RestEndpoint`, `resource()` and `.extend()` - -Editors and `tsc` check code that defines or calls endpoints faster and with less memory. In our stress tests, a file of 150 RestEndpoints with long paths, `.extend()` and `.paginated()` checked in about half the time (3.1s → 1.6s) and memory (345MB → 207MB). Files that use `resource()` with React or Vue hooks did 22-25% less type work. TypeScript reports the same errors as before. - -On TypeScript 5.x and earlier, a `process(value, params)` method passed to `.extend()` no longer fails with "implicitly has an 'any' type" under `strict`, matching TypeScript 6+. TypeScript 4.0 also accepts a chained `.extend().extend()`. - -```ts -const getUser = new RestEndpoint({ path: '/users/:id', schema: User }); - -// Before (TypeScript 5.x and earlier): error TS7006: Parameter 'value' implicitly has an 'any' type. -// After: no error -const getUserName = getUser.extend({ - process(value, params) { - return value.name; - }, -}); -``` diff --git a/.changeset/fetch-meta-promise.md b/.changeset/fetch-meta-promise.md deleted file mode 100644 index a957d2e4b41d..000000000000 --- a/.changeset/fetch-meta-promise.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/react': patch -'@data-client/vue': patch ---- - -Type FETCH `action.meta.promise` as `Promise` - -Managers can now call `.finally()` and `.catch()` on a FETCH action's `meta.promise` without a TypeScript error. It was always a real `Promise` at runtime, but was typed `PromiseLike`, which only has `.then()`. - -```ts -// Before: TypeScript error on .finally(), so both callbacks went to .then() -const track = () => - trackTiming(action.endpoint.name, performance.now() - start); -action.meta.promise.then(track, track); - -// After -action.meta.promise - .finally(() => { - trackTiming(action.endpoint.name, performance.now() - start); - }) - // the fetch's caller handles errors; this only observes timing - .catch(() => {}); -``` diff --git a/.changeset/fixture-args-readonly.md b/.changeset/fixture-args-readonly.md deleted file mode 100644 index e95a5a622954..000000000000 --- a/.changeset/fixture-args-readonly.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/test': patch -'@data-client/react': patch -'@data-client/vue': patch ---- - -Fixture `args` accept readonly tuples - -Fixtures written with `args: [...] as const` now type-check when passed to [MockResolver](https://dataclient.io/docs/api/MockResolver), `renderDataHook()`, Vue's `renderDataCompose()` or `mockInitialState()`. Before, TypeScript rejected them with "The type 'readonly [...]' is 'readonly' and cannot be assigned to the mutable type", so you had to drop `as const` or cast. - -```ts -const fixtures = [ - { - endpoint: TodoResource.getList, - args: [{ userId: 1 }] as const, - response: [{ id: 1, title: 'Write tests', userId: 1 }], - }, -]; - -// Before: type error on `fixtures`. After: works as written - - -; -``` diff --git a/.changeset/legacy-ts-endpoint-libcheck.md b/.changeset/legacy-ts-endpoint-libcheck.md deleted file mode 100644 index 6fde9e1a81a8..000000000000 --- a/.changeset/legacy-ts-endpoint-libcheck.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -'@data-client/endpoint': patch -'@data-client/rest': patch -'@data-client/graphql': patch ---- - -Fix more TypeScript 4.x errors when `skipLibCheck` is off - -[Entity](https://dataclient.io/rest/api/Entity), [Endpoint](https://dataclient.io/rest/api/Endpoint), [Union](https://dataclient.io/rest/api/Union) and [RestEndpoint](https://dataclient.io/rest/api/RestEndpoint) declarations no longer report errors on TypeScript 4.0 through 4.5. On TypeScript 4.0 and 4.1, an `Entity` can be an `Endpoint` schema again. - -```ts -import { Endpoint, Entity, schema } from '@data-client/endpoint'; - -class User extends Entity { - id = ''; - type = 'users'; -} -const getUser = new Endpoint( - (id: string) => fetch(`/users/${id}`).then(res => res.json()), - { schema: User }, -); -const feed = new schema.Union({ users: User }, 'type'); - -// Before (TypeScript 4.0, skipLibCheck: false): -// error TS2456: Type alias 'RemoveArray' circularly references itself. -// error TS2322: Type 'typeof User' is not assignable to type 'EntityInterface'. -// Before (TypeScript 4.2): -// error TS2344: Type 'TBase' does not satisfy the constraint 'new (...args: any) => any'. -// After: no errors -``` diff --git a/.changeset/legacy-ts-inline-type-imports.md b/.changeset/legacy-ts-inline-type-imports.md deleted file mode 100644 index 53d69390bc54..000000000000 --- a/.changeset/legacy-ts-inline-type-imports.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@data-client/react': patch -'@data-client/test': patch -'@data-client/vue': patch ---- - -Fix `',' expected` errors on TypeScript 4.0 through 4.4 - -Importing `@data-client/react/redux`, `@data-client/react/nextjs` or `@data-client/test` failed to compile on TypeScript before 4.5, even with `skipLibCheck` on, because their declaration files used syntax those versions can't parse. They now compile on TypeScript 4.0 and later. - -```ts -import { DataProvider } from '@data-client/react/nextjs'; -import { renderDataHook } from '@data-client/test'; - -// Before (TypeScript 4.0 to 4.4): -// node_modules/@data-client/react/lib/server/nextjs/DataProvider/DataProvider.d.ts(1,15): error TS1005: ',' expected. -// node_modules/@data-client/test/lib/makeRenderDataClient/index.d.ts(3,33): error TS1005: ',' expected. -// After: no errors -``` - -`@data-client/vue/test` types now also resolve with `moduleResolution: "node"`. diff --git a/.changeset/legacy-ts-noinfer.md b/.changeset/legacy-ts-noinfer.md deleted file mode 100644 index d27ac8b61936..000000000000 --- a/.changeset/legacy-ts-noinfer.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -'@data-client/endpoint': patch -'@data-client/normalizr': patch -'@data-client/rest': patch -'@data-client/graphql': patch -'@data-client/react': patch -'@data-client/vue': patch ---- - -Fix types for TypeScript 4.x when `skipLibCheck` is off - -TypeScript 4.0 through 4.7 no longer report `Cannot find name 'NoInfer'` from `@data-client/endpoint` or `@data-client/normalizr`, and TypeScript 4.0 through 4.9 no longer report `Only named exports may use 'export type'` from `@data-client/normalizr`. - -```ts -import { Entity } from '@data-client/endpoint'; -import { normalize } from '@data-client/normalizr'; - -// Before (TypeScript 4.7, skipLibCheck: false): -// error TS2304: Cannot find name 'NoInfer'. -// error TS1383: Only named exports may use 'export type'. -// After: no errors -``` diff --git a/.changeset/manager-middleware-required.md b/.changeset/manager-middleware-required.md deleted file mode 100644 index 1eb1b4df2475..000000000000 --- a/.changeset/manager-middleware-required.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -'@data-client/core': minor -'@data-client/react': minor -'@data-client/vue': minor ---- - -BREAKING: [Manager.middleware](https://dataclient.io/docs/api/Manager#middleware) is required; `getMiddleware()` is removed - -A Manager without `middleware`, including one that still uses `getMiddleware()` (replaced in v0.14), is now a -TypeScript error, and throws in development when `DataProvider` or `DataClientPlugin` mounts. Rename `getMiddleware()` -to a `middleware` property: - -```ts -// before -getMiddleware = (): Middleware => controller => next => async action => next(action); -// after -middleware: Middleware = controller => next => async action => next(action); -``` diff --git a/.changeset/manager-without-middleware.md b/.changeset/manager-without-middleware.md deleted file mode 100644 index 08730cc76036..000000000000 --- a/.changeset/manager-without-middleware.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/react': patch -'@data-client/vue': patch ---- - -Clear error for a [Manager](https://dataclient.io/docs/api/Manager) without `middleware` - -A Manager must define [middleware](https://dataclient.io/docs/api/Manager#middleware). One without it used to crash -with `manager.middleware is not a function`; in development it now throws an error naming the Manager and linking to -the docs. diff --git a/.changeset/max-entity-depth-jsdoc.md b/.changeset/max-entity-depth-jsdoc.md deleted file mode 100644 index b02a3c7a6a7c..000000000000 --- a/.changeset/max-entity-depth-jsdoc.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@data-client/endpoint': patch -'@data-client/rest': patch -'@data-client/graphql': patch ---- - -Fix `Entity.maxEntityDepth` docs: the default is 64, not 128 - -Editor hover docs for `static maxEntityDepth` now show the real default. Runtime behavior is unchanged; set `maxEntityDepth` explicitly if you relied on 128. diff --git a/.changeset/native-focus-refetch.md b/.changeset/native-focus-refetch.md deleted file mode 100644 index c0918799fb2c..000000000000 --- a/.changeset/native-focus-refetch.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@data-client/react': patch ---- - -Fix React Native screens refetching fresh data every time they regain focus - -On React Native, [useSuspense()](https://dataclient.io/docs/api/useSuspense), [useFetch()](https://dataclient.io/docs/api/useFetch) -and [useDLE()](https://dataclient.io/docs/api/useDLE) revalidate when a screen comes back into focus. They checked -the expiry from the screen's first render, so once that data went stale, every refocus refetched it, even right after -a fetch had made it fresh. After the arguments changed, they could also refetch the old arguments. - -Refocusing now refetches only when the current data is [stale](https://dataclient.io/docs/concepts/expiry-policy#stale) -or [invalid](https://dataclient.io/docs/concepts/expiry-policy#invalid), using the current arguments. diff --git a/.changeset/optimistic-response-types.md b/.changeset/optimistic-response-types.md deleted file mode 100644 index 2a80bc3707b4..000000000000 --- a/.changeset/optimistic-response-types.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -'@data-client/endpoint': patch -'@data-client/rest': patch -'@data-client/graphql': patch ---- - -Fix `getOptimisticResponse()` accepting any return value - -Unless an endpoint has a typed `process()`, its [getOptimisticResponse()](https://dataclient.io/rest/api/RestEndpoint#getoptimisticresponse) -could return anything, so a wrong field type only showed up as bad data in the UI until the server responded. The return -value is now checked against the endpoint's schema, like a [Controller.set()](https://dataclient.io/docs/api/Controller#set) -value: an Entity takes any of its fields, and a [Collection](https://dataclient.io/rest/api/Collection) takes a list of them. -This applies to `new RestEndpoint()`, `.extend()` and `resource().extend()`. - -```ts -const toggleTodo = new RestEndpoint({ - path: '/todos/:id', - method: 'PATCH', - schema: Todo, - getOptimisticResponse(snap, { id }) { - const todo = snap.get(Todo, { id }); - if (!todo) throw snap.abort; - // Before: compiled, then the checkbox stayed checked because 'false' is truthy - // After: TypeScript error, completed is a boolean - return { id, completed: todo.completed ? 'false' : 'true' }; - }, -}); -``` - -Return the field's real type instead (`completed: !todo.completed`). Endpoints with a typed `process()` keep checking -the return against what `process()` returns. diff --git a/.changeset/prepare-store-redux-store.md b/.changeset/prepare-store-redux-store.md deleted file mode 100644 index 56a96c4c14fc..000000000000 --- a/.changeset/prepare-store-redux-store.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -'@data-client/react': patch ---- - -Fix TypeScript error passing `prepareStore()`'s store to react-redux's `` - -`prepareStore()` from `@data-client/react/redux` typed its `store` as a minimal object with only `getState()` and `subscribe()`, so [using it with React-Redux](https://dataclient.io/docs/guides/redux) needed a cast, and `store.dispatch()` was a TypeScript error. It's now typed as a Redux `Store`. Its `replaceReducer()` and `[Symbol.observable]()` aren't supported: they throw, and are typed as returning `never`. - -```tsx -const { store, selector, controller } = prepareStore( - initialState, - managers, - Controller, - otherReducers, - extraMiddlewares, -); - -// Before: TypeScript error, so you had to cast - - -// After - -``` diff --git a/.changeset/query-collection-push-body.md b/.changeset/query-collection-push-body.md deleted file mode 100644 index c5e9c39975b7..000000000000 --- a/.changeset/query-collection-push-body.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -'@data-client/rest': patch ---- - -Fix `RestEndpoint.push`, `unshift` and `remove` body types when a `Query` or `Lazy` wraps the endpoint's `Collection` - -Sorting or filtering a list with a [Query](https://dataclient.io/rest/api/Query) around its [Collection](https://dataclient.io/rest/api/Collection) made `getPosts.push` reject every body except `FormData`, though it adds to the list at runtime. The body is now typed from the Collection's Entity, so a correct body compiles and a wrong field is a TypeScript error. The same applies to a Collection wrapped in [Lazy](https://dataclient.io/rest/api/Lazy). - -```ts -const getPosts = new RestEndpoint({ - path: '/:group/posts', - searchParams: {} as { orderBy?: string }, - schema: new Query( - new Collection([Post], { nonFilterArgumentKeys: /orderBy/ }), - (posts, { orderBy } = {}) => sortBy(posts, orderBy), - ), -}); -``` - -If you cast the body to get past this error, the cast can go: - -```ts -// Before -ctrl.fetch(getPosts.push, { group: 'react' }, { title, author } as any); -// After -ctrl.fetch(getPosts.push, { group: 'react' }, { title, author }); -``` diff --git a/.changeset/react-native-087.md b/.changeset/react-native-087.md deleted file mode 100644 index c345b17f1f5b..000000000000 --- a/.changeset/react-native-087.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@data-client/react': patch ---- - -Support React Native 0.87 - -React Native 0.87 removed `InteractionManager`, so apps on it crashed as soon as a component called `useSuspense()`, `useFetch()` or `useDLE()`. On 0.87 and later, Data Client now waits for idle time with `requestIdleCallback()`, as React Native recommends. Older React Native versions keep using `InteractionManager`. diff --git a/.changeset/render-data-hook-suspend-effects.md b/.changeset/render-data-hook-suspend-effects.md deleted file mode 100644 index 51fa328c9bff..000000000000 --- a/.changeset/render-data-hook-suspend-effects.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@data-client/test': patch ---- - -Fix mount effects when `renderDataHook()` suspends on the first render - -`renderDataHook()` and `makeRenderDataHook()` now run provider mount effects when the first render suspends, including `use(useFetch())`. The hook result stays unresolved until the data arrives. diff --git a/.changeset/resource-create-formdata.md b/.changeset/resource-create-formdata.md deleted file mode 100644 index a9f03cdffaba..000000000000 --- a/.changeset/resource-create-formdata.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@data-client/rest': patch ---- - -Fix TypeScript error passing `FormData` to `resource().create` - -`resource().create` sends a `FormData` body as-is, the same as `update`, `partialUpdate` and -`getList.push`, but its type only allowed an object, so submitting a form needed a cast. This now typechecks, -and you can drop the cast. `create` is deprecated, and its replacement `getList.push` takes `FormData` too. - -```tsx -
{ - e.preventDefault(); - // Before: TypeScript error, so you had to cast - ctrl.fetch(PostResource.create, new FormData(e.currentTarget) as any); - // After - ctrl.fetch(PostResource.create, new FormData(e.currentTarget)); - }} -> -``` diff --git a/.changeset/resource-extend-keeps-members.md b/.changeset/resource-extend-keeps-members.md deleted file mode 100644 index 159bcaf420b7..000000000000 --- a/.changeset/resource-extend-keeps-members.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -'@data-client/rest': patch ---- - -Fix `resource().extend({ get: ... })` dropping endpoints added earlier from its type - -Customizing a resource's standard endpoints with `.extend({ ... })` kept every endpoint at runtime, but TypeScript lost the ones added before it with `.extend('name', options)`, and the deprecated `create`. Using them was a type error even though they worked. - -```ts -const UserResource = resource({ path: '/users/:id', schema: User }) - .extend('current', { path: '/user' }) - .extend({ get: { dataExpiryLength: 60000 } }); - -// Before: Property 'current' does not exist -// After: no error -const me = await ctrl.fetch(UserResource.current); -``` diff --git a/.changeset/rest-array-body-json.md b/.changeset/rest-array-body-json.md deleted file mode 100644 index 03cd09a1223a..000000000000 --- a/.changeset/rest-array-body-json.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@data-client/rest': patch ---- - -Fix pushing several items at once sending `"[object Object]"` instead of JSON - -[RestEndpoint.push](https://dataclient.io/rest/api/RestEndpoint#push), `unshift` and `remove` accept an array of items, -but sent it to `fetch()` as-is, so the server received `"[object Object],[object Object]"` with no JSON `Content-Type`. Arrays are -now JSON-encoded like objects, with `Content-Type: application/json`. `FormData`, `Blob`, `URLSearchParams` and strings -still go to `fetch()` unchanged. - -`resource().create` takes the same bodies as `getList.push`, including an array. - -```ts -// Before: the server received "[object Object],[object Object]" -// After: the server receives [{"title":"Buy milk"},{"title":"Walk dog"}] -await ctrl.fetch(TodoResource.getList.push, [ - { title: 'Buy milk' }, - { title: 'Walk dog' }, -]); -``` diff --git a/.changeset/test-mock-reexports.md b/.changeset/test-mock-reexports.md deleted file mode 100644 index 08c42a7f26e1..000000000000 --- a/.changeset/test-mock-reexports.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -'@data-client/test': minor ---- - -BREAKING: `@data-client/test` requires `@data-client/react` 0.15.3 or later - -Support for `@data-client/react` 0.12 through 0.15.2 is dropped, since `@data-client/test` imports -`@data-client/react/mock`, which first loads in Jest and other CommonJS tests in 0.15.3. Upgrade `@data-client/react` -along with `@data-client/test`. - -```diff title="package.json" -- "@data-client/react": "^0.14.0", -+ "@data-client/react": "^0.19.0", -``` - -`Fixture`, `Interceptor`, and the other fixture types from `@data-client/test` are now the same types that -`@data-client/react/mock` exports, so fixtures typed with either import work everywhere. diff --git a/.changeset/test-renderhook-ts4.md b/.changeset/test-renderhook-ts4.md deleted file mode 100644 index dfbe30431d2f..000000000000 --- a/.changeset/test-renderhook-ts4.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -'@data-client/test': patch ---- - -Fix `act` and `renderHook` typed as `any` on TypeScript 4.0–4.4 - -`act()`, `renderHook()` and `RenderHookOptions` from `@data-client/test` were `any` on TypeScript 4.0–4.4, and -reported `Cannot find module './renderHook.cjs'` with `skipLibCheck` off. They now have their real types: - -```ts -import { act, renderHook } from '@data-client/test'; - -const { result } = renderHook(() => 5); -result.current; // number -await act(() => Promise.resolve(5)); // number -``` diff --git a/.changeset/test-rntl-14.md b/.changeset/test-rntl-14.md deleted file mode 100644 index dc04d35db4a2..000000000000 --- a/.changeset/test-rntl-14.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@data-client/test': patch ---- - -Support React Native Testing Library 14 - -[renderDataHook()](https://dataclient.io/docs/api/renderDataHook) keeps working on React Native after upgrading to `@testing-library/react-native` 14, and stays synchronous, so existing `renderDataHook()` calls need no `await`. Install `test-renderer`, which RNTL 14 needs anyway. Projects on RNTL 13 keep working unchanged. diff --git a/.changeset/typescript7-exports.md b/.changeset/typescript7-exports.md deleted file mode 100644 index fa5015883d27..000000000000 --- a/.changeset/typescript7-exports.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -'@data-client/core': patch -'@data-client/endpoint': patch -'@data-client/graphql': patch -'@data-client/img': patch -'@data-client/normalizr': patch -'@data-client/react': patch -'@data-client/rest': patch -'@data-client/test': patch -'@data-client/vue': patch ---- - -Fix TypeScript 7 module resolution for package exports - -TypeScript 7 requires a `types` condition in `package.json` `exports`. Without it, imports resolved to runtime entrypoints like `node.mjs` and lost declaration files. diff --git a/.changeset/vue-create-data-client-internal.md b/.changeset/vue-create-data-client-internal.md deleted file mode 100644 index 0499b5909891..000000000000 --- a/.changeset/vue-create-data-client-internal.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -'@data-client/vue': patch ---- - -`createDataClient()` and `ProvidedDataClient` are deprecated - -They only exist to implement [DataClientPlugin](https://dataclient.io/vue/api/DataClientPlugin) and will stop being -exported in a future release. Nothing changes at runtime. If you call `createDataClient()` directly, install the -plugin instead and read the controller with [useController()](https://dataclient.io/vue/api/useController). - -```ts title="main.ts" -import { DataClientPlugin } from '@data-client/vue'; - -app.use(DataClientPlugin, { managers, initialState }); -``` diff --git a/.changeset/vue-default-gcpolicy.md b/.changeset/vue-default-gcpolicy.md deleted file mode 100644 index 0bf139ffba2a..000000000000 --- a/.changeset/vue-default-gcpolicy.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -'@data-client/vue': patch ---- - -`DataClientPlugin` garbage collects by default - -Previously, unused data was only removed from the store if you passed a `gcPolicy` yourself. It now defaults -to `new GCPolicy()`, matching `DataProvider` in `@data-client/react`, so you can drop the option unless you -customize it. - -Before - -```ts -import { DataClientPlugin, GCPolicy } from '@data-client/vue'; - -app.use(DataClientPlugin, { gcPolicy: new GCPolicy() }); -``` - -After - -```ts -import { DataClientPlugin } from '@data-client/vue'; - -app.use(DataClientPlugin); -``` diff --git a/.changeset/vue-deprecate-wait-for-next-update.md b/.changeset/vue-deprecate-wait-for-next-update.md deleted file mode 100644 index 0bc08d01e146..000000000000 --- a/.changeset/vue-deprecate-wait-for-next-update.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -'@data-client/vue': patch ---- - -`waitForNextUpdate()` from `renderDataCompose()` is deprecated - -It gives up silently after 1 second, so a test could pass while the composable was still suspended. When the Promise -had already resolved, it waited the full second for nothing, and under `jest.useFakeTimers()` it could hang. Await the -result directly instead, and use `allSettled()` after changing props or calling the controller. - -`allSettled()` from `renderDataCompose()` and `mountDataClient()` now also waits for fetches that a prop change starts, -and for the component to re-render, so you no longer need `nextTick()` around it. It also waits on a `NetworkManager` -you pass in `managers`, instead of returning right away. - -#### Before - -```ts -import { reactive } from 'vue'; - -const props = reactive({ id: 5 }); -const { result, waitForNextUpdate } = await renderDataCompose( - (props: { id: number }) => - useSuspense(ArticleResource.get, () => ({ id: props.id })), - { props, resolverFixtures }, -); -await waitForNextUpdate(); -const article = await result; - -props.id = 6; -await waitForNextUpdate(); -``` - -#### After - -```ts -import { reactive } from 'vue'; - -const props = reactive({ id: 5 }); -const { result, allSettled } = await renderDataCompose( - (props: { id: number }) => - useSuspense(ArticleResource.get, () => ({ id: props.id })), - { props, resolverFixtures }, -); -const article = await result; - -props.id = 6; -await allSettled(); -``` diff --git a/.changeset/vue-expiry-stable.md b/.changeset/vue-expiry-stable.md deleted file mode 100644 index d1c04480c3cc..000000000000 --- a/.changeset/vue-expiry-stable.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@data-client/vue': patch ---- - -Fix `useDLE()` and `useCache()` dropping expired `invalidIfStale` data on unrelated store updates - -After an `invalidIfStale` response expired, any unrelated store update switched these composables to empty data, and -`useDLE()` stayed `loading` without starting a fetch. Expiry is now only re-checked when the response's expiry, the -arguments, or a reset changes, matching `@data-client/react`. - -The `vue` peer dependency is now `^3.4.0`. - -```ts -const { data, loading } = useDLE(ArticleResource.get, { id: 5 }); -// ...after the response's dataExpiryLength passes -await ctrl.setResponse(UserResource.get, { id: 1 }, user); -// Before: loading.value === true, data.value === undefined, and no fetch starts -// After: loading.value === false, data.value is still the article -``` diff --git a/.changeset/vue-export-gcpolicy.md b/.changeset/vue-export-gcpolicy.md deleted file mode 100644 index be01e9cd5664..000000000000 --- a/.changeset/vue-export-gcpolicy.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -'@data-client/vue': patch ---- - -Export `GCPolicy` from `@data-client/vue` - -```ts -// Before -import { GCPolicy } from '@data-client/core'; -// After -import { GCPolicy } from '@data-client/vue'; - -app.use(DataClientPlugin, { - gcPolicy: new GCPolicy({ intervalMS: 60 * 1000 * 10 }), -}); -``` diff --git a/.changeset/vue-getter-args.md b/.changeset/vue-getter-args.md deleted file mode 100644 index 6bbd4a387d7e..000000000000 --- a/.changeset/vue-getter-args.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@data-client/vue': patch ---- - -Fix getter function arguments in Vue composables - -`useSuspense`, `useLive`, `useCache`, `useDLE`, `useFetch`, `useQuery` and `useSubscription` -were typed to accept getter functions as arguments, but only resolved refs at runtime. Getters -now work and are tracked reactively, just like refs and `computed`. - -```ts -const props = defineProps<{ id: number }>(); - -// Before: getter was passed to the endpoint as-is -// After: re-fetches when props.id changes -const article = await useSuspense(ArticleResource.get, () => ({ - id: props.id, -})); -``` diff --git a/.changeset/vue-internal-exports.md b/.changeset/vue-internal-exports.md deleted file mode 100644 index d909188fe613..000000000000 --- a/.changeset/vue-internal-exports.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@data-client/vue': patch ---- - -Add `__INTERNAL__` export matching `@data-client/react`'s - -Tooling built on `@data-client/vue` can now use `createReducer`, `initialState` and friends without adding `@data-client/core` as a direct dependency. diff --git a/.changeset/vue-plugin-onunmount.md b/.changeset/vue-plugin-onunmount.md deleted file mode 100644 index cb43925e503a..000000000000 --- a/.changeset/vue-plugin-onunmount.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@data-client/vue': patch ---- - -Fix `app.use(DataClientPlugin)` throwing `app.onUnmount is not a function` on Vue versions before 3.5 - -```ts -const app = createApp(App); -// Before (Vue < 3.5): TypeError: app.onUnmount is not a function -// After: installs, and stops the DataClient when the app unmounts -app.use(DataClientPlugin); -``` diff --git a/.changeset/vue-stale-refetch.md b/.changeset/vue-stale-refetch.md deleted file mode 100644 index 7d50ffaf00d4..000000000000 --- a/.changeset/vue-stale-refetch.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -'@data-client/vue': patch ---- - -Fix `useSuspense()`, `useDLE()` and `useFetch()` refetching stale data on every store update - -Once data was stale, any store update (such as `controller.set()`) made these composables refetch, so the server -response could overwrite the change. They now only refetch when the data's expiry, the arguments, or a reset changes, -matching `@data-client/react`. - -```ts -const article = await useSuspense(ArticleResource.get, { id: 5 }); -// ...after the response's dataExpiryLength passes -await ctrl.set(Article, { id: 5 }, { id: 5, title: 'edited' }); -// Before: triggers a refetch that reverts title to the server value -// After: title stays 'edited' -``` diff --git a/.changeset/vue-suspense-arg-errors.md b/.changeset/vue-suspense-arg-errors.md deleted file mode 100644 index 2006d403f3e7..000000000000 --- a/.changeset/vue-suspense-arg-errors.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@data-client/vue': patch ---- - -Fix `useSuspense()` and `useLive()` fetch errors after arguments change being unhandled - -When ref or computed arguments changed and the new fetch failed, the error became an unhandled promise rejection -and the result became `undefined`. Reading the result now throws the error, like the first load does, so it reaches -`onErrorCaptured()`. - -```ts -const props = defineProps<{ id: number }>(); -const todo = await useSuspense( - TodoResource.get, - computed(() => ({ id: props.id })), -); -// Before: a failed fetch for a new id was an unhandled rejection; todo.value became undefined -// After: reading todo.value throws the fetch error, caught by onErrorCaptured() -``` diff --git a/.changeset/vue-suspense-keep-previous.md b/.changeset/vue-suspense-keep-previous.md deleted file mode 100644 index 5514d24bbc06..000000000000 --- a/.changeset/vue-suspense-keep-previous.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -'@data-client/vue': patch ---- - -Fix `useSuspense()` and `useLive()` returning `undefined` while new arguments load - -When ref or computed arguments changed to data not yet in the store, the result became `undefined` until the -new fetch resolved, crashing templates like `{{ todo.title }}`. It now keeps the previous data until the new data arrives. - -```ts -const props = defineProps<{ id: number }>(); -const todo = await useSuspense(TodoResource.get, computed(() => ({ id: props.id }))); -// Before: todo.value was undefined while the new id loaded -// After: todo.value keeps the previous todo until the new one arrives -``` diff --git a/.changeset/vue-suspense-stale-while-revalidate.md b/.changeset/vue-suspense-stale-while-revalidate.md deleted file mode 100644 index 48a6b1470f03..000000000000 --- a/.changeset/vue-suspense-stale-while-revalidate.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@data-client/vue': patch ---- - -Fix Vue `useSuspense()` suspending on stale data instead of showing it while it refetches - -When a component mounted with cached data that was past its `dataExpiryLength` but still valid, `await useSuspense()` -waited for the refetch, so users saw the `` fallback instead of the data already on hand. Now, like React, -it renders the stale data right away and updates once the refetch resolves. Data that is missing, invalidated, or -[invalidIfStale](https://dataclient.io/rest/api/Endpoint#invalidifstale) still waits for the fetch. diff --git a/.changeset/vue-usefetch-gc.md b/.changeset/vue-usefetch-gc.md deleted file mode 100644 index 53e34a097179..000000000000 --- a/.changeset/vue-usefetch-gc.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@data-client/vue': patch ---- - -Vue `useFetch()` keeps its response from being garbage collected while mounted, like React `useFetch()` and Vue `useSuspense()` diff --git a/.changeset/vue-usefetch-ref-type.md b/.changeset/vue-usefetch-ref-type.md deleted file mode 100644 index efe2d3f82a2c..000000000000 --- a/.changeset/vue-usefetch-ref-type.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -'@data-client/vue': patch ---- - -Fix [useFetch()](https://dataclient.io/docs/api/useFetch) return type to be a read-only `Ref` - -`useFetch()` returns a read-only `Ref` holding the fetch promise, but was typed as returning the promise directly. - -```ts -const promise = useFetch(PostResource.get, { id }); -// Before: promise.resolved typechecked, but was always undefined at runtime -// After: -if (!promise.value.resolved) { - // fetch is in-flight -} -``` diff --git a/examples/benchmark-react/CHANGELOG.md b/examples/benchmark-react/CHANGELOG.md index ec05eb6974fe..36e22719cda5 100644 --- a/examples/benchmark-react/CHANGELOG.md +++ b/examples/benchmark-react/CHANGELOG.md @@ -1,5 +1,15 @@ # example-benchmark-react +## 0.1.12 + +### Patch Changes + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`46f1f24`](https://github.com/reactive/data-client/commit/46f1f24bcb04824805747ed2a1effe7baece337c), [`a82758c`](https://github.com/reactive/data-client/commit/a82758cd1998e58d7ad280407db28bd84f5d7b18), [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee), [`c3b8c54`](https://github.com/reactive/data-client/commit/c3b8c54bc3062cf082e67c215310cb98b3a03078), [`b1d40fd`](https://github.com/reactive/data-client/commit/b1d40fd80c9aa292f5cdbce9b573e7749d889069), [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`159c963`](https://github.com/reactive/data-client/commit/159c9633679d95427fe4f626aec341c76e4578f8), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e), [`a73b437`](https://github.com/reactive/data-client/commit/a73b437c8f60ef8c64266874ea82e5119dfe4874), [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7), [`47502c6`](https://github.com/reactive/data-client/commit/47502c664df913297fba3e5011a975dfd01c0d8d), [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`31b1820`](https://github.com/reactive/data-client/commit/31b182033106d5ce44352481577d3c321e39ebe9), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`31f3ddb`](https://github.com/reactive/data-client/commit/31f3ddbc178ade2a7f59f7029a54c416df70e003), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336), [`954b1e9`](https://github.com/reactive/data-client/commit/954b1e9041ba47b39b9ffdd53a55b0b16adc8675), [`643d818`](https://github.com/reactive/data-client/commit/643d818ac757a0218e91d9523879e25024c5e61f), [`4829b10`](https://github.com/reactive/data-client/commit/4829b1033a24f52e2a1d0e5a03532f9cfa4f525f), [`588a558`](https://github.com/reactive/data-client/commit/588a558332d9d2bc6a313b2f4b6700bb3ff017f2), [`bf377f4`](https://github.com/reactive/data-client/commit/bf377f46a2c916d8e808472645f1da9704ffaf91), [`ae7080d`](https://github.com/reactive/data-client/commit/ae7080de64ca8621833a71267ec84d2a9d5e19dd), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/core@0.19.0 + - @data-client/endpoint@0.19.0 + - @data-client/react@0.19.0 + - @data-client/rest@0.19.0 + ## 0.1.11 ### Patch Changes diff --git a/examples/benchmark-react/package.json b/examples/benchmark-react/package.json index 42a08edffe3f..6b937d971886 100644 --- a/examples/benchmark-react/package.json +++ b/examples/benchmark-react/package.json @@ -1,6 +1,6 @@ { "name": "example-benchmark-react", - "version": "0.1.11", + "version": "0.1.12", "private": true, "description": "React rendering benchmark comparing @data-client/react against other data libraries", "scripts": { diff --git a/examples/benchmark/CHANGELOG.md b/examples/benchmark/CHANGELOG.md index 257c96bafb41..537b4d77fc19 100644 --- a/examples/benchmark/CHANGELOG.md +++ b/examples/benchmark/CHANGELOG.md @@ -1,5 +1,14 @@ # example-benchmark +## 0.4.87 + +### Patch Changes + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`46f1f24`](https://github.com/reactive/data-client/commit/46f1f24bcb04824805747ed2a1effe7baece337c), [`a82758c`](https://github.com/reactive/data-client/commit/a82758cd1998e58d7ad280407db28bd84f5d7b18), [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee), [`c3b8c54`](https://github.com/reactive/data-client/commit/c3b8c54bc3062cf082e67c215310cb98b3a03078), [`b1d40fd`](https://github.com/reactive/data-client/commit/b1d40fd80c9aa292f5cdbce9b573e7749d889069), [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`159c963`](https://github.com/reactive/data-client/commit/159c9633679d95427fe4f626aec341c76e4578f8), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e), [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7), [`47502c6`](https://github.com/reactive/data-client/commit/47502c664df913297fba3e5011a975dfd01c0d8d), [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`31f3ddb`](https://github.com/reactive/data-client/commit/31f3ddbc178ade2a7f59f7029a54c416df70e003), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176), [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/core@0.19.0 + - @data-client/endpoint@0.19.0 + - @data-client/normalizr@0.19.0 + ## 0.4.86 ### Patch Changes diff --git a/examples/benchmark/package.json b/examples/benchmark/package.json index b18f26c56b20..6df1707b9778 100644 --- a/examples/benchmark/package.json +++ b/examples/benchmark/package.json @@ -1,6 +1,6 @@ { "name": "example-benchmark", - "version": "0.4.86", + "version": "0.4.87", "description": "Benchmark for normalizr", "main": "index.js", "author": "Nathaniel Tucker", diff --git a/examples/coin-app/CHANGELOG.md b/examples/coin-app/CHANGELOG.md index c9f467f6af27..746712e28cf8 100644 --- a/examples/coin-app/CHANGELOG.md +++ b/examples/coin-app/CHANGELOG.md @@ -1,5 +1,14 @@ # coinbase-lite +## 0.0.27 + +### Patch Changes + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`46f1f24`](https://github.com/reactive/data-client/commit/46f1f24bcb04824805747ed2a1effe7baece337c), [`a82758c`](https://github.com/reactive/data-client/commit/a82758cd1998e58d7ad280407db28bd84f5d7b18), [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee), [`c3b8c54`](https://github.com/reactive/data-client/commit/c3b8c54bc3062cf082e67c215310cb98b3a03078), [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`159c963`](https://github.com/reactive/data-client/commit/159c9633679d95427fe4f626aec341c76e4578f8), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e), [`a73b437`](https://github.com/reactive/data-client/commit/a73b437c8f60ef8c64266874ea82e5119dfe4874), [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7), [`47502c6`](https://github.com/reactive/data-client/commit/47502c664df913297fba3e5011a975dfd01c0d8d), [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`31b1820`](https://github.com/reactive/data-client/commit/31b182033106d5ce44352481577d3c321e39ebe9), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`31f3ddb`](https://github.com/reactive/data-client/commit/31f3ddbc178ade2a7f59f7029a54c416df70e003), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336), [`954b1e9`](https://github.com/reactive/data-client/commit/954b1e9041ba47b39b9ffdd53a55b0b16adc8675), [`643d818`](https://github.com/reactive/data-client/commit/643d818ac757a0218e91d9523879e25024c5e61f), [`4829b10`](https://github.com/reactive/data-client/commit/4829b1033a24f52e2a1d0e5a03532f9cfa4f525f), [`588a558`](https://github.com/reactive/data-client/commit/588a558332d9d2bc6a313b2f4b6700bb3ff017f2), [`bf377f4`](https://github.com/reactive/data-client/commit/bf377f46a2c916d8e808472645f1da9704ffaf91), [`ae7080d`](https://github.com/reactive/data-client/commit/ae7080de64ca8621833a71267ec84d2a9d5e19dd), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/react@0.19.0 + - @data-client/rest@0.19.0 + - @data-client/img@0.19.0 + ## 0.0.26 ### Patch Changes diff --git a/examples/coin-app/package.json b/examples/coin-app/package.json index fff9f0d28de6..dcff4ba35acd 100644 --- a/examples/coin-app/package.json +++ b/examples/coin-app/package.json @@ -1,6 +1,6 @@ { "name": "coinbase-lite", - "version": "0.0.26", + "version": "0.0.27", "packageManager": "yarn@4.18.1", "description": "Coin App", "scripts": { @@ -44,9 +44,9 @@ "@anansi/core": "0.23.1", "@anansi/router": "0.11.1", "@babel/runtime-corejs3": "8.0.7", - "@data-client/img": "0.18.0", - "@data-client/react": "0.18.1", - "@data-client/rest": "0.18.1", + "@data-client/img": "0.19.0", + "@data-client/react": "0.19.0", + "@data-client/rest": "0.19.0", "core-js": "3.50.0", "d3": "7.9.0", "history": "*", diff --git a/examples/normalizr-github/CHANGELOG.md b/examples/normalizr-github/CHANGELOG.md index 89d77408ee04..1057ee67d5f0 100644 --- a/examples/normalizr-github/CHANGELOG.md +++ b/examples/normalizr-github/CHANGELOG.md @@ -1,5 +1,13 @@ # normalizr-github-example +## 0.1.61 + +### Patch Changes + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e), [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176), [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/endpoint@0.19.0 + - @data-client/normalizr@0.19.0 + ## 0.1.60 ### Patch Changes diff --git a/examples/normalizr-github/package.json b/examples/normalizr-github/package.json index b422cd9890c7..79b2a55fac57 100644 --- a/examples/normalizr-github/package.json +++ b/examples/normalizr-github/package.json @@ -1,6 +1,6 @@ { "name": "normalizr-github-example", - "version": "0.1.60", + "version": "0.1.61", "description": "And example of using Normalizr with github", "main": "index.js", "author": "Paul Armstrong", diff --git a/examples/normalizr-redux/CHANGELOG.md b/examples/normalizr-redux/CHANGELOG.md index 81b58d556372..0f8fe773f01a 100644 --- a/examples/normalizr-redux/CHANGELOG.md +++ b/examples/normalizr-redux/CHANGELOG.md @@ -1,5 +1,13 @@ # normalizr-redux-example +## 0.1.59 + +### Patch Changes + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e), [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176), [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/endpoint@0.19.0 + - @data-client/normalizr@0.19.0 + ## 0.1.58 ### Patch Changes diff --git a/examples/normalizr-redux/package.json b/examples/normalizr-redux/package.json index 288ffd7f31a6..f096a8f1f79c 100644 --- a/examples/normalizr-redux/package.json +++ b/examples/normalizr-redux/package.json @@ -1,6 +1,6 @@ { "name": "normalizr-redux-example", - "version": "0.1.58", + "version": "0.1.59", "description": "And example of using Normalizr with Redux", "main": "index.js", "author": "Paul Armstrong", diff --git a/examples/normalizr-relationships/CHANGELOG.md b/examples/normalizr-relationships/CHANGELOG.md index e8c96a48c801..8dc42dafa489 100644 --- a/examples/normalizr-relationships/CHANGELOG.md +++ b/examples/normalizr-relationships/CHANGELOG.md @@ -1,5 +1,13 @@ # normalizr-relationships +## 0.1.61 + +### Patch Changes + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e), [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176), [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/endpoint@0.19.0 + - @data-client/normalizr@0.19.0 + ## 0.1.60 ### Patch Changes diff --git a/examples/normalizr-relationships/package.json b/examples/normalizr-relationships/package.json index a890593fe634..648d0f95fca0 100644 --- a/examples/normalizr-relationships/package.json +++ b/examples/normalizr-relationships/package.json @@ -1,6 +1,6 @@ { "name": "normalizr-relationships", - "version": "0.1.60", + "version": "0.1.61", "description": "And example of using Normalizr with relationships", "main": "index.js", "author": "Paul Armstrong", diff --git a/examples/test-bundlesize/CHANGELOG.md b/examples/test-bundlesize/CHANGELOG.md index 5ec2987e68b5..5aa40c8ece25 100644 --- a/examples/test-bundlesize/CHANGELOG.md +++ b/examples/test-bundlesize/CHANGELOG.md @@ -1,5 +1,14 @@ # test-bundlesize +## 0.1.19 + +### Patch Changes + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`46f1f24`](https://github.com/reactive/data-client/commit/46f1f24bcb04824805747ed2a1effe7baece337c), [`a82758c`](https://github.com/reactive/data-client/commit/a82758cd1998e58d7ad280407db28bd84f5d7b18), [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee), [`c3b8c54`](https://github.com/reactive/data-client/commit/c3b8c54bc3062cf082e67c215310cb98b3a03078), [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`159c963`](https://github.com/reactive/data-client/commit/159c9633679d95427fe4f626aec341c76e4578f8), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e), [`a73b437`](https://github.com/reactive/data-client/commit/a73b437c8f60ef8c64266874ea82e5119dfe4874), [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7), [`47502c6`](https://github.com/reactive/data-client/commit/47502c664df913297fba3e5011a975dfd01c0d8d), [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`31b1820`](https://github.com/reactive/data-client/commit/31b182033106d5ce44352481577d3c321e39ebe9), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`31f3ddb`](https://github.com/reactive/data-client/commit/31f3ddbc178ade2a7f59f7029a54c416df70e003), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336), [`954b1e9`](https://github.com/reactive/data-client/commit/954b1e9041ba47b39b9ffdd53a55b0b16adc8675), [`643d818`](https://github.com/reactive/data-client/commit/643d818ac757a0218e91d9523879e25024c5e61f), [`4829b10`](https://github.com/reactive/data-client/commit/4829b1033a24f52e2a1d0e5a03532f9cfa4f525f), [`588a558`](https://github.com/reactive/data-client/commit/588a558332d9d2bc6a313b2f4b6700bb3ff017f2), [`bf377f4`](https://github.com/reactive/data-client/commit/bf377f46a2c916d8e808472645f1da9704ffaf91), [`ae7080d`](https://github.com/reactive/data-client/commit/ae7080de64ca8621833a71267ec84d2a9d5e19dd), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/react@0.19.0 + - @data-client/rest@0.19.0 + - @data-client/img@0.19.0 + ## 0.1.18 ### Patch Changes diff --git a/examples/test-bundlesize/package.json b/examples/test-bundlesize/package.json index 8e35e467a4bf..e40268aac8af 100644 --- a/examples/test-bundlesize/package.json +++ b/examples/test-bundlesize/package.json @@ -1,6 +1,6 @@ { "name": "test-bundlesize", - "version": "0.1.18", + "version": "0.1.19", "packageManager": "yarn@4.18.1", "description": "Testing Bundled Size", "scripts": { diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md new file mode 100644 index 000000000000..eaf1378922ba --- /dev/null +++ b/packages/codemods/CHANGELOG.md @@ -0,0 +1,13 @@ +# @data-client/codemods + +## 0.1.0 + +### Minor Changes + +- [#4409](https://github.com/reactive/data-client/pull/4409) [`7d1c42a`](https://github.com/reactive/data-client/commit/7d1c42add1a00089a8ff604086cd0a2d295bbb45) - New package: run Data Client codemods with `npx @data-client/codemods ` + + The codemods ship on npm with each release, instead of being fetched from dataclient.io at run time. + + ```bash + npx @data-client/codemods v0.18 src/ + ``` diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 635d7e033326..cd0788466d81 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,6 +1,6 @@ { "name": "@data-client/codemods", - "version": "0.0.0", + "version": "0.1.0", "description": "Codemods that migrate code to new Reactive Data Client releases", "homepage": "https://dataclient.io/blog", "repository": { diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index e01840bfa1f6..cd82559123fe 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,244 @@ # @data-client/core +## 0.19.0 + +### Minor Changes + +- [#4151](https://github.com/reactive/data-client/pull/4151) [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e) - BREAKING: Require TypeScript 4.0 or later + + The TypeScript 3.x type declarations are removed. They no longer type-checked on any TypeScript 3.x version, and + `@data-client/rest` already required TypeScript 4.0. Upgrade TypeScript to 4.0 or later. + + ```diff title="package.json" + - "typescript": "^3.9.0" + + "typescript": "^4.0.0" + ``` + +- [#4382](https://github.com/reactive/data-client/pull/4382) [`31f3ddb`](https://github.com/reactive/data-client/commit/31f3ddbc178ade2a7f59f7029a54c416df70e003) - BREAKING: [Manager.middleware](https://dataclient.io/docs/api/Manager#middleware) is required; `getMiddleware()` is removed + + A Manager without `middleware`, including one that still uses `getMiddleware()` (replaced in v0.14), is now a + TypeScript error, and throws in development when `DataProvider` or `DataClientPlugin` mounts. Rename `getMiddleware()` + to a `middleware` property: + + ```ts + // before + getMiddleware = (): Middleware => controller => next => async action => + next(action); + // after + middleware: Middleware = controller => next => async action => next(action); + ``` + +### Patch Changes + +- [#4407](https://github.com/reactive/data-client/pull/4407) [`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb) - Ship agent skills inside the packages + + Coding agents can now follow the skills for the version you have installed instead of guessing from older releases. Each package carries the skills it covers, and the new `data-client-skills` command (in `@data-client/react`, `vue`, `rest`, `graphql` and `endpoint`, so repos with only API definitions get it too) links them into `.agents/skills`, with `.claude/skills` linking to it, where Claude Code, Cursor and Codex load them as their own: + + ```bash + npx --no data-client-skills + ``` + + Commit the links. They point into `node_modules`, so they follow upgrades; run it again after adding, removing or upgrading `@data-client` packages to pick up new skills. [TanStack Intent](https://tanstack.com/intent) also finds these skills. + +- [#4209](https://github.com/reactive/data-client/pull/4209) [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169) Thanks [@renovate](https://github.com/apps/renovate)! - Support `@babel/runtime` 8 + + Apps on Babel 8 now share their `@babel/runtime` with Data Client instead of installing a second copy. Apps on Babel 7 keep working unchanged. + +- [#4103](https://github.com/reactive/data-client/pull/4103) [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69) - Fix `controller.set()` types for Array schemas + + `controller.set([Entity], rows)` and `controller.set(new schema.Array(Entity), rows)` now typecheck. This writes every row in one store update: each row merges with its stored entity, and entities not in `rows` stay. This works with `exactOptionalPropertyTypes` on too. + + Rows are typed by the Entity's fields. The schema holds one Entity, [Union](https://dataclient.io/rest/api/Union) (for mixed types) or [Invalidate](https://dataclient.io/rest/api/Invalidate) (to delete), in an Array or [Values](https://dataclient.io/rest/api/Values) (which takes an object keyed by id). + + Batch `set()` needs `@data-client/rest` (or `endpoint`/`graphql`) from this release, since older Entity classes don't type as `EntityInterface`. + + ```ts + // Before: TypeScript error on [Ticker], so batches became one set() per row + for (const row of rows) { + ctrl.set(Ticker, { product_id: row.product_id }, row); + } + + // After: one store update + ctrl.set([Ticker], rows); + + // Mixed Entity types, batch deletes, and rows keyed by id + const Message = new schema.Union({ ticker: Ticker, trade: Trade }, 'type'); + ctrl.set([Message], messages); + ctrl.set([new schema.Invalidate(Ticker)], [{ product_id: 'BTC-USD' }]); + ctrl.set(new schema.Values(Ticker), { 'BTC-USD': row }); + ``` + +- [#4230](https://github.com/reactive/data-client/pull/4230) [`46f1f24`](https://github.com/reactive/data-client/commit/46f1f24bcb04824805747ed2a1effe7baece337c) - Fix `controller.set()` types for a single [Invalidate](https://dataclient.io/rest/api/Invalidate) + + Deleting one entity with `set()` worked at runtime but failed to typecheck, since `Invalidate` isn't + [Queryable](https://dataclient.io/rest/api/schema#queryable). Pass the schema and the row to delete; the row is typed + by the Entity's fields. + + ```ts + // Before: TypeScript error, so a one-row batch was the workaround + ctrl.set([new Invalidate(Post)], [{ id: '5' }]); + + // After + ctrl.set(new Invalidate(Post), { id: '5' }); + ``` + + Like batch `set()`, it takes no `args` and no updater function. + +- [#4133](https://github.com/reactive/data-client/pull/4133) [`a82758c`](https://github.com/reactive/data-client/commit/a82758cd1998e58d7ad280407db28bd84f5d7b18) - Fix `controller.set()` accepting any value + + Values are now typed by the schema: Entities take their fields, while [Collection](https://dataclient.io/rest/api/Collection) + and [All](https://dataclient.io/rest/api/All) take a list of rows. [Query](https://dataclient.io/rest/api/Query) takes + the input of the schema it wraps, not what its `process()` returns. Updater functions must return the same. + + ```ts + // Before: these all typechecked, then failed or wrote nothing at runtime + ctrl.set(new schema.All(Todo), 42); + ctrl.set(TodoResource.getList.schema, 'anything'); + ctrl.set(Todo, { id: '5' }, { id: '5', completed: 'yes' }); + + // After: TypeScript errors on the above; these typecheck + ctrl.set(TodoResource.getList.schema, [{ id: '5', completed: true }]); + ctrl.set(new schema.All(Todo), [{ id: '5', completed: true }]); + ``` + + When each member declares its discriminator as a literal (like `readonly type = 'post'`), a + [Union](https://dataclient.io/rest/api/Union) row is checked against the member it selects. Only + declared fields are accepted, so a key read by a `schemaAttribute` function must be declared on each member. + + ```ts + const Feed = new schema.Union({ post: Post, comment: Comment }, 'type'); + // TypeScript error: commentBody is a Comment field, not a Post field + ctrl.set( + Feed, + { id: '1', type: 'post' }, + { type: 'post', commentBody: 'hi' }, + ); + ``` + +- [#4228](https://github.com/reactive/data-client/pull/4228) [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee) - Fix TypeScript error passing a `Controller` subclass to `DataProvider` or `DataClientPlugin` + + A plain `class MyController extends Controller` failed to typecheck as the `Controller` option of [DataProvider](https://dataclient.io/docs/api/DataProvider#Controller), Vue's [DataClientPlugin](https://dataclient.io/vue/api/DataClientPlugin#Controller), and the `@data-client/react/redux` `DataProvider`, so the documented example needed a cast. `MockController()` from `@data-client/core/mock` had the same error when wrapping your subclass. These now typecheck, and you can drop the casts. + + ```tsx + class MyController extends Controller { + doSomething = () => console.log('hi'); + } + + // Before: TypeScript error, so you had to cast + + app.use(DataClientPlugin, { Controller: MyController as typeof Controller }); + + // After + + app.use(DataClientPlugin, { Controller: MyController }); + ``` + +- [#4420](https://github.com/reactive/data-client/pull/4420) [`c3b8c54`](https://github.com/reactive/data-client/commit/c3b8c54bc3062cf082e67c215310cb98b3a03078) - Fix fixture types needing `@data-client/endpoint` installed + + `Fixture` and the other fixture types from `@data-client/react/mock`, `@data-client/core/mock` and `@data-client/test` no + longer resolve `@data-client/endpoint`, which those packages don't depend on. Projects that install only + `@data-client/react` and `@data-client/test` (for example with pnpm's strict layout) no longer get + `Cannot find module '@data-client/endpoint'` when type-checking fixtures. + +- [#4408](https://github.com/reactive/data-client/pull/4408) [`b1d40fd`](https://github.com/reactive/data-client/commit/b1d40fd80c9aa292f5cdbce9b573e7749d889069) - Ship a `data-client` agent skill that routes "use Data Client" to setup + + Asking your coding agent to use Data Client in an app without it now reaches the setup skill, which installs the packages and adds the provider. In apps that have it, the skill points your agent at the skill for the task. + +- [#4150](https://github.com/reactive/data-client/pull/4150) [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2) - Fix `useCache()` and `useDLE()` returning a truthy `Symbol` for deleted entities + + After an entity was deleted and its refetch failed, `useCache()` and `useDLE()` (React and Vue) returned an internal + `Symbol` instead of `undefined`. Since a `Symbol` is truthy, "not loaded" checks passed, and code went on to use it as + the entity: + + ```tsx + const todo = useCache(TodoResource.get, { id }); + if (!todo) return ; + // Before: reached here with a Symbol; todo.title was undefined and todo.title.trim() threw + // After: the placeholder renders + return ; + ``` + + [Controller.getResponse()](https://dataclient.io/docs/api/Controller#getResponse) and + [Controller.fetchIfStale()](https://dataclient.io/docs/api/Controller#fetchIfStale) now also give `undefined` there, + like [Controller.get()](https://dataclient.io/docs/api/Controller#get) already did. + +- [#4393](https://github.com/reactive/data-client/pull/4393) [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23) - Add recent actions to `globalThis.__DC_ACTIONS__` in development + + Coding agents and console debugging can now see what each store dispatched, including the fetches made while the + page loaded, without the Redux DevTools extension. [DevToolsManager](https://dataclient.io/docs/api/DevToolsManager#controllers) + keeps each store's recent actions in a `Map` keyed like `__DC_CONTROLLERS__`. Production builds don't include it. + + To keep memory small, only the newest 20 actions keep their payloads, and each polling key (endpoint and args) keeps + only its last two polls (`maxPollingActions`, default 4 actions). + + ```js title="Browser DevTools console" + __DC_ACTIONS__.get('Data Client: My App').slice(-10); + ``` + +- [#4163](https://github.com/reactive/data-client/pull/4163) [`159c963`](https://github.com/reactive/data-client/commit/159c9633679d95427fe4f626aec341c76e4578f8) - Fix slow updates in development while Redux DevTools is open + + With the [Redux DevTools](https://dataclient.io/docs/getting-started/debugging) extension open, every store update + stalled the page while DevTools serialized the store: about 20ms with 50 entities, and 200ms with 500. Apps doing + many `controller.set()` calls, polling, or live updates would stutter in development. Each update now serializes + 40-60x faster, and timestamps still show as readable times like `10:42:07.123 AM`. + +- [#4393](https://github.com/reactive/data-client/pull/4393) [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23) - Fix stores with the same devtools name hiding each other in `__DC_CONTROLLERS__` + + With two `DataProvider`s, or two Vue apps using `DataClientPlugin`, on one page and the default devtools name, the + second store replaced the first in `globalThis.__DC_CONTROLLERS__`, so debugging tools and coding agents could only find one. The second now + registers as `'Data Client: My App (2)'`, the next as `(3)`, and so on. + +- [#4227](https://github.com/reactive/data-client/pull/4227) [`47502c6`](https://github.com/reactive/data-client/commit/47502c664df913297fba3e5011a975dfd01c0d8d) - Type FETCH `action.meta.promise` as `Promise` + + Managers can now call `.finally()` and `.catch()` on a FETCH action's `meta.promise` without a TypeScript error. It was always a real `Promise` at runtime, but was typed `PromiseLike`, which only has `.then()`. + + ```ts + // Before: TypeScript error on .finally(), so both callbacks went to .then() + const track = () => + trackTiming(action.endpoint.name, performance.now() - start); + action.meta.promise.then(track, track); + + // After + action.meta.promise + .finally(() => { + trackTiming(action.endpoint.name, performance.now() - start); + }) + // the fetch's caller handles errors; this only observes timing + .catch(() => {}); + ``` + +- [#4250](https://github.com/reactive/data-client/pull/4250) [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a) - Fixture `args` accept readonly tuples + + Fixtures written with `args: [...] as const` now type-check when passed to [MockResolver](https://dataclient.io/docs/api/MockResolver), `renderDataHook()`, Vue's `renderDataCompose()` or `mockInitialState()`. Before, TypeScript rejected them with "The type 'readonly [...]' is 'readonly' and cannot be assigned to the mutable type", so you had to drop `as const` or cast. + + ```ts + const fixtures = [ + { + endpoint: TodoResource.getList, + args: [{ userId: 1 }] as const, + response: [{ id: 1, title: 'Write tests', userId: 1 }], + }, + ]; + + // Before: type error on `fixtures`. After: works as written + + + ; + ``` + +- [#4378](https://github.com/reactive/data-client/pull/4378) [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53) - Clear error for a [Manager](https://dataclient.io/docs/api/Manager) without `middleware` + + A Manager must define [middleware](https://dataclient.io/docs/api/Manager#middleware). One without it used to crash + with `manager.middleware is not a function`; in development it now throws an error naming the Manager and linking to + the docs. + +- [#4019](https://github.com/reactive/data-client/pull/4019) [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e) Thanks [@renovate](https://github.com/apps/renovate)! - Fix TypeScript 7 module resolution for package exports + + TypeScript 7 requires a `types` condition in `package.json` `exports`. Without it, imports resolved to runtime entrypoints like `node.mjs` and lost declaration files. + +- Updated dependencies [[`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/normalizr@0.19.0 + ## 0.18.1 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index 562a73ec4d66..ef6fb3311f47 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@data-client/core", - "version": "0.18.1", + "version": "0.19.0", "description": "Async State Management without the Management. REST, GraphQL, SSE, Websockets, Fetch", "sideEffects": false, "main": "dist/index.js", diff --git a/packages/endpoint/CHANGELOG.md b/packages/endpoint/CHANGELOG.md index d6d9ac031109..0c26cc6e3d42 100644 --- a/packages/endpoint/CHANGELOG.md +++ b/packages/endpoint/CHANGELOG.md @@ -1,5 +1,148 @@ # @data-client/endpoint +## 0.19.0 + +### Minor Changes + +- [#4151](https://github.com/reactive/data-client/pull/4151) [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e) - BREAKING: Require TypeScript 4.0 or later + + The TypeScript 3.x type declarations are removed. They no longer type-checked on any TypeScript 3.x version, and + `@data-client/rest` already required TypeScript 4.0. Upgrade TypeScript to 4.0 or later. + + ```diff title="package.json" + - "typescript": "^3.9.0" + + "typescript": "^4.0.0" + ``` + +### Patch Changes + +- [#4407](https://github.com/reactive/data-client/pull/4407) [`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb) - Ship agent skills inside the packages + + Coding agents can now follow the skills for the version you have installed instead of guessing from older releases. Each package carries the skills it covers, and the new `data-client-skills` command (in `@data-client/react`, `vue`, `rest`, `graphql` and `endpoint`, so repos with only API definitions get it too) links them into `.agents/skills`, with `.claude/skills` linking to it, where Claude Code, Cursor and Codex load them as their own: + + ```bash + npx --no data-client-skills + ``` + + Commit the links. They point into `node_modules`, so they follow upgrades; run it again after adding, removing or upgrading `@data-client` packages to pick up new skills. [TanStack Intent](https://tanstack.com/intent) also finds these skills. + +- [#4209](https://github.com/reactive/data-client/pull/4209) [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169) Thanks [@renovate](https://github.com/apps/renovate)! - Support `@babel/runtime` 8 + + Apps on Babel 8 now share their `@babel/runtime` with Data Client instead of installing a second copy. Apps on Babel 7 keep working unchanged. + +- [#4149](https://github.com/reactive/data-client/pull/4149) [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e) - Fix Entity classes not assignable to `EntityInterface` + + [Entity.pk()](https://dataclient.io/rest/api/Entity#pk)'s static `args` parameter is now `readonly any[]`, matching `EntityInterface`. Entity classes can be passed where an `EntityInterface` is expected. + + ```ts + import type { EntityInterface } from '@data-client/react'; + + // Before: TypeScript error (args is readonly in EntityInterface) + // After: typechecks + const schema: EntityInterface = User; + ``` + + Overrides of `static pk()` that type `args` as a mutable array still compile, but a future breaking release will require `readonly any[]`, so update them now: + + ```ts + class User extends Entity { + static pk(value: any, parent?: any, key?: string, args?: readonly any[]) { + return `${value.id}-${args?.[0]?.org}`; + } + } + ``` + +- [#4173](https://github.com/reactive/data-client/pull/4173) [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7) - Speed up TypeScript checking of `RestEndpoint`, `resource()` and `.extend()` + + Editors and `tsc` check code that defines or calls endpoints faster and with less memory. In our stress tests, a file of 150 RestEndpoints with long paths, `.extend()` and `.paginated()` checked in about half the time (3.1s → 1.6s) and memory (345MB → 207MB). Files that use `resource()` with React or Vue hooks did 22-25% less type work. TypeScript reports the same errors as before. + + On TypeScript 5.x and earlier, a `process(value, params)` method passed to `.extend()` no longer fails with "implicitly has an 'any' type" under `strict`, matching TypeScript 6+. TypeScript 4.0 also accepts a chained `.extend().extend()`. + + ```ts + const getUser = new RestEndpoint({ path: '/users/:id', schema: User }); + + // Before (TypeScript 5.x and earlier): error TS7006: Parameter 'value' implicitly has an 'any' type. + // After: no error + const getUserName = getUser.extend({ + process(value, params) { + return value.name; + }, + }); + ``` + +- [#4122](https://github.com/reactive/data-client/pull/4122) [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc) - Fix more TypeScript 4.x errors when `skipLibCheck` is off + + [Entity](https://dataclient.io/rest/api/Entity), [Endpoint](https://dataclient.io/rest/api/Endpoint), [Union](https://dataclient.io/rest/api/Union) and [RestEndpoint](https://dataclient.io/rest/api/RestEndpoint) declarations no longer report errors on TypeScript 4.0 through 4.5. On TypeScript 4.0 and 4.1, an `Entity` can be an `Endpoint` schema again. + + ```ts + import { Endpoint, Entity, schema } from '@data-client/endpoint'; + + class User extends Entity { + id = ''; + type = 'users'; + } + const getUser = new Endpoint( + (id: string) => fetch(`/users/${id}`).then(res => res.json()), + { schema: User }, + ); + const feed = new schema.Union({ users: User }, 'type'); + + // Before (TypeScript 4.0, skipLibCheck: false): + // error TS2456: Type alias 'RemoveArray' circularly references itself. + // error TS2322: Type 'typeof User' is not assignable to type 'EntityInterface'. + // Before (TypeScript 4.2): + // error TS2344: Type 'TBase' does not satisfy the constraint 'new (...args: any) => any'. + // After: no errors + ``` + +- [#4122](https://github.com/reactive/data-client/pull/4122) [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc) - Fix types for TypeScript 4.x when `skipLibCheck` is off + + TypeScript 4.0 through 4.7 no longer report `Cannot find name 'NoInfer'` from `@data-client/endpoint` or `@data-client/normalizr`, and TypeScript 4.0 through 4.9 no longer report `Only named exports may use 'export type'` from `@data-client/normalizr`. + + ```ts + import { Entity } from '@data-client/endpoint'; + import { normalize } from '@data-client/normalizr'; + + // Before (TypeScript 4.7, skipLibCheck: false): + // error TS2304: Cannot find name 'NoInfer'. + // error TS1383: Only named exports may use 'export type'. + // After: no errors + ``` + +- [#4224](https://github.com/reactive/data-client/pull/4224) [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176) - Fix `Entity.maxEntityDepth` docs: the default is 64, not 128 + + Editor hover docs for `static maxEntityDepth` now show the real default. Runtime behavior is unchanged; set `maxEntityDepth` explicitly if you relied on 128. + +- [#4198](https://github.com/reactive/data-client/pull/4198) [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336) - Fix `getOptimisticResponse()` accepting any return value + + Unless an endpoint has a typed `process()`, its [getOptimisticResponse()](https://dataclient.io/rest/api/RestEndpoint#getoptimisticresponse) + could return anything, so a wrong field type only showed up as bad data in the UI until the server responded. The return + value is now checked against the endpoint's schema, like a [Controller.set()](https://dataclient.io/docs/api/Controller#set) + value: an Entity takes any of its fields, and a [Collection](https://dataclient.io/rest/api/Collection) takes a list of them. + This applies to `new RestEndpoint()`, `.extend()` and `resource().extend()`. + + ```ts + const toggleTodo = new RestEndpoint({ + path: '/todos/:id', + method: 'PATCH', + schema: Todo, + getOptimisticResponse(snap, { id }) { + const todo = snap.get(Todo, { id }); + if (!todo) throw snap.abort; + // Before: compiled, then the checkbox stayed checked because 'false' is truthy + // After: TypeScript error, completed is a boolean + return { id, completed: todo.completed ? 'false' : 'true' }; + }, + }); + ``` + + Return the field's real type instead (`completed: !todo.completed`). Endpoints with a typed `process()` keep checking + the return against what `process()` returns. + +- [#4019](https://github.com/reactive/data-client/pull/4019) [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e) Thanks [@renovate](https://github.com/apps/renovate)! - Fix TypeScript 7 module resolution for package exports + + TypeScript 7 requires a `types` condition in `package.json` `exports`. Without it, imports resolved to runtime entrypoints like `node.mjs` and lost declaration files. + ## 0.18.0 ### Minor Changes diff --git a/packages/endpoint/package.json b/packages/endpoint/package.json index 04a0e7a0cb27..a452d002c138 100644 --- a/packages/endpoint/package.json +++ b/packages/endpoint/package.json @@ -1,6 +1,6 @@ { "name": "@data-client/endpoint", - "version": "0.18.0", + "version": "0.19.0", "description": "Declarative Network Interface Definitions", "homepage": "https://dataclient.io/docs/guides/custom-protocol", "keywords": [ diff --git a/packages/graphql/CHANGELOG.md b/packages/graphql/CHANGELOG.md index 5fa37aaf13bd..4ff8dbbd84b3 100644 --- a/packages/graphql/CHANGELOG.md +++ b/packages/graphql/CHANGELOG.md @@ -1,5 +1,151 @@ # @data-client/graphql +## 0.19.0 + +### Minor Changes + +- [#4151](https://github.com/reactive/data-client/pull/4151) [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e) - BREAKING: Require TypeScript 4.0 or later + + The TypeScript 3.x type declarations are removed. They no longer type-checked on any TypeScript 3.x version, and + `@data-client/rest` already required TypeScript 4.0. Upgrade TypeScript to 4.0 or later. + + ```diff title="package.json" + - "typescript": "^3.9.0" + + "typescript": "^4.0.0" + ``` + +### Patch Changes + +- [#4407](https://github.com/reactive/data-client/pull/4407) [`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb) - Ship agent skills inside the packages + + Coding agents can now follow the skills for the version you have installed instead of guessing from older releases. Each package carries the skills it covers, and the new `data-client-skills` command (in `@data-client/react`, `vue`, `rest`, `graphql` and `endpoint`, so repos with only API definitions get it too) links them into `.agents/skills`, with `.claude/skills` linking to it, where Claude Code, Cursor and Codex load them as their own: + + ```bash + npx --no data-client-skills + ``` + + Commit the links. They point into `node_modules`, so they follow upgrades; run it again after adding, removing or upgrading `@data-client` packages to pick up new skills. [TanStack Intent](https://tanstack.com/intent) also finds these skills. + +- [#4209](https://github.com/reactive/data-client/pull/4209) [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169) Thanks [@renovate](https://github.com/apps/renovate)! - Support `@babel/runtime` 8 + + Apps on Babel 8 now share their `@babel/runtime` with Data Client instead of installing a second copy. Apps on Babel 7 keep working unchanged. + +- [#4149](https://github.com/reactive/data-client/pull/4149) [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e) - Fix Entity classes not assignable to `EntityInterface` + + [Entity.pk()](https://dataclient.io/rest/api/Entity#pk)'s static `args` parameter is now `readonly any[]`, matching `EntityInterface`. Entity classes can be passed where an `EntityInterface` is expected. + + ```ts + import type { EntityInterface } from '@data-client/react'; + + // Before: TypeScript error (args is readonly in EntityInterface) + // After: typechecks + const schema: EntityInterface = User; + ``` + + Overrides of `static pk()` that type `args` as a mutable array still compile, but a future breaking release will require `readonly any[]`, so update them now: + + ```ts + class User extends Entity { + static pk(value: any, parent?: any, key?: string, args?: readonly any[]) { + return `${value.id}-${args?.[0]?.org}`; + } + } + ``` + +- [#4173](https://github.com/reactive/data-client/pull/4173) [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7) - Speed up TypeScript checking of `RestEndpoint`, `resource()` and `.extend()` + + Editors and `tsc` check code that defines or calls endpoints faster and with less memory. In our stress tests, a file of 150 RestEndpoints with long paths, `.extend()` and `.paginated()` checked in about half the time (3.1s → 1.6s) and memory (345MB → 207MB). Files that use `resource()` with React or Vue hooks did 22-25% less type work. TypeScript reports the same errors as before. + + On TypeScript 5.x and earlier, a `process(value, params)` method passed to `.extend()` no longer fails with "implicitly has an 'any' type" under `strict`, matching TypeScript 6+. TypeScript 4.0 also accepts a chained `.extend().extend()`. + + ```ts + const getUser = new RestEndpoint({ path: '/users/:id', schema: User }); + + // Before (TypeScript 5.x and earlier): error TS7006: Parameter 'value' implicitly has an 'any' type. + // After: no error + const getUserName = getUser.extend({ + process(value, params) { + return value.name; + }, + }); + ``` + +- [#4122](https://github.com/reactive/data-client/pull/4122) [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc) - Fix more TypeScript 4.x errors when `skipLibCheck` is off + + [Entity](https://dataclient.io/rest/api/Entity), [Endpoint](https://dataclient.io/rest/api/Endpoint), [Union](https://dataclient.io/rest/api/Union) and [RestEndpoint](https://dataclient.io/rest/api/RestEndpoint) declarations no longer report errors on TypeScript 4.0 through 4.5. On TypeScript 4.0 and 4.1, an `Entity` can be an `Endpoint` schema again. + + ```ts + import { Endpoint, Entity, schema } from '@data-client/endpoint'; + + class User extends Entity { + id = ''; + type = 'users'; + } + const getUser = new Endpoint( + (id: string) => fetch(`/users/${id}`).then(res => res.json()), + { schema: User }, + ); + const feed = new schema.Union({ users: User }, 'type'); + + // Before (TypeScript 4.0, skipLibCheck: false): + // error TS2456: Type alias 'RemoveArray' circularly references itself. + // error TS2322: Type 'typeof User' is not assignable to type 'EntityInterface'. + // Before (TypeScript 4.2): + // error TS2344: Type 'TBase' does not satisfy the constraint 'new (...args: any) => any'. + // After: no errors + ``` + +- [#4122](https://github.com/reactive/data-client/pull/4122) [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc) - Fix types for TypeScript 4.x when `skipLibCheck` is off + + TypeScript 4.0 through 4.7 no longer report `Cannot find name 'NoInfer'` from `@data-client/endpoint` or `@data-client/normalizr`, and TypeScript 4.0 through 4.9 no longer report `Only named exports may use 'export type'` from `@data-client/normalizr`. + + ```ts + import { Entity } from '@data-client/endpoint'; + import { normalize } from '@data-client/normalizr'; + + // Before (TypeScript 4.7, skipLibCheck: false): + // error TS2304: Cannot find name 'NoInfer'. + // error TS1383: Only named exports may use 'export type'. + // After: no errors + ``` + +- [#4224](https://github.com/reactive/data-client/pull/4224) [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176) - Fix `Entity.maxEntityDepth` docs: the default is 64, not 128 + + Editor hover docs for `static maxEntityDepth` now show the real default. Runtime behavior is unchanged; set `maxEntityDepth` explicitly if you relied on 128. + +- [#4198](https://github.com/reactive/data-client/pull/4198) [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336) - Fix `getOptimisticResponse()` accepting any return value + + Unless an endpoint has a typed `process()`, its [getOptimisticResponse()](https://dataclient.io/rest/api/RestEndpoint#getoptimisticresponse) + could return anything, so a wrong field type only showed up as bad data in the UI until the server responded. The return + value is now checked against the endpoint's schema, like a [Controller.set()](https://dataclient.io/docs/api/Controller#set) + value: an Entity takes any of its fields, and a [Collection](https://dataclient.io/rest/api/Collection) takes a list of them. + This applies to `new RestEndpoint()`, `.extend()` and `resource().extend()`. + + ```ts + const toggleTodo = new RestEndpoint({ + path: '/todos/:id', + method: 'PATCH', + schema: Todo, + getOptimisticResponse(snap, { id }) { + const todo = snap.get(Todo, { id }); + if (!todo) throw snap.abort; + // Before: compiled, then the checkbox stayed checked because 'false' is truthy + // After: TypeScript error, completed is a boolean + return { id, completed: todo.completed ? 'false' : 'true' }; + }, + }); + ``` + + Return the field's real type instead (`completed: !todo.completed`). Endpoints with a typed `process()` keep checking + the return against what `process()` returns. + +- [#4019](https://github.com/reactive/data-client/pull/4019) [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e) Thanks [@renovate](https://github.com/apps/renovate)! - Fix TypeScript 7 module resolution for package exports + + TypeScript 7 requires a `types` condition in `package.json` `exports`. Without it, imports resolved to runtime entrypoints like `node.mjs` and lost declaration files. + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e), [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176), [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/endpoint@0.19.0 + ## 0.18.0 ### Minor Changes diff --git a/packages/graphql/package.json b/packages/graphql/package.json index a9715e4aaafa..f977c9bad611 100644 --- a/packages/graphql/package.json +++ b/packages/graphql/package.json @@ -1,6 +1,6 @@ { "name": "@data-client/graphql", - "version": "0.18.0", + "version": "0.19.0", "description": "Quickly define typed GraphQL resources and endpoints", "homepage": "https://dataclient.io/docs/graphql", "repository": { diff --git a/packages/img/CHANGELOG.md b/packages/img/CHANGELOG.md index 6d2724a68cb3..74898753646d 100644 --- a/packages/img/CHANGELOG.md +++ b/packages/img/CHANGELOG.md @@ -1,5 +1,33 @@ # @data-client/img +## 0.19.0 + +### Minor Changes + +- [#4151](https://github.com/reactive/data-client/pull/4151) [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e) - BREAKING: Require TypeScript 4.0 or later + + The TypeScript 3.x type declarations are removed. They no longer type-checked on any TypeScript 3.x version, and + `@data-client/rest` already required TypeScript 4.0. Upgrade TypeScript to 4.0 or later. + + ```diff title="package.json" + - "typescript": "^3.9.0" + + "typescript": "^4.0.0" + ``` + +### Patch Changes + +- [#4209](https://github.com/reactive/data-client/pull/4209) [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169) Thanks [@renovate](https://github.com/apps/renovate)! - Support `@babel/runtime` 8 + + Apps on Babel 8 now share their `@babel/runtime` with Data Client instead of installing a second copy. Apps on Babel 7 keep working unchanged. + +- [#4019](https://github.com/reactive/data-client/pull/4019) [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e) Thanks [@renovate](https://github.com/apps/renovate)! - Fix TypeScript 7 module resolution for package exports + + TypeScript 7 requires a `types` condition in `package.json` `exports`. Without it, imports resolved to runtime entrypoints like `node.mjs` and lost declaration files. + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`46f1f24`](https://github.com/reactive/data-client/commit/46f1f24bcb04824805747ed2a1effe7baece337c), [`a82758c`](https://github.com/reactive/data-client/commit/a82758cd1998e58d7ad280407db28bd84f5d7b18), [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee), [`c3b8c54`](https://github.com/reactive/data-client/commit/c3b8c54bc3062cf082e67c215310cb98b3a03078), [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`159c963`](https://github.com/reactive/data-client/commit/159c9633679d95427fe4f626aec341c76e4578f8), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e), [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7), [`47502c6`](https://github.com/reactive/data-client/commit/47502c664df913297fba3e5011a975dfd01c0d8d), [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`31b1820`](https://github.com/reactive/data-client/commit/31b182033106d5ce44352481577d3c321e39ebe9), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`31f3ddb`](https://github.com/reactive/data-client/commit/31f3ddbc178ade2a7f59f7029a54c416df70e003), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336), [`954b1e9`](https://github.com/reactive/data-client/commit/954b1e9041ba47b39b9ffdd53a55b0b16adc8675), [`4829b10`](https://github.com/reactive/data-client/commit/4829b1033a24f52e2a1d0e5a03532f9cfa4f525f), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/endpoint@0.19.0 + - @data-client/react@0.19.0 + ## 0.18.0 ### Patch Changes diff --git a/packages/img/package.json b/packages/img/package.json index 4d906ea0dbc1..a6f39df36b77 100644 --- a/packages/img/package.json +++ b/packages/img/package.json @@ -1,6 +1,6 @@ { "name": "@data-client/img", - "version": "0.18.0", + "version": "0.19.0", "description": "Suspenseful images", "homepage": "https://dataclient.io/docs/guides/img-media#just-images", "repository": { @@ -68,7 +68,7 @@ "@data-client/endpoint": "workspace:^" }, "peerDependencies": { - "@data-client/react": "^0.1.0 || ^0.2.0 || ^0.3.0 || ^0.4.0 || ^0.5.0 || ^0.7.0 || ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^0.14.0 || ^0.15.0 || ^0.16.0 || ^0.17.0 || ^0.18.0", + "@data-client/react": "^0.19.0", "@types/react": "^16.14.0 || ^17.0.0 || ^18.0.0-0 || ^19.0.0", "react": "^16.14.0 || ^17.0.0 || ^18.0.0-0 || ^19.0.0" }, diff --git a/packages/normalizr/CHANGELOG.md b/packages/normalizr/CHANGELOG.md index ab480b23caf5..f2bc31878aa7 100644 --- a/packages/normalizr/CHANGELOG.md +++ b/packages/normalizr/CHANGELOG.md @@ -1,5 +1,67 @@ # Change Log +## 0.19.0 + +### Minor Changes + +- [#4151](https://github.com/reactive/data-client/pull/4151) [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e) - BREAKING: Require TypeScript 4.0 or later + + The TypeScript 3.x type declarations are removed. They no longer type-checked on any TypeScript 3.x version, and + `@data-client/rest` already required TypeScript 4.0. Upgrade TypeScript to 4.0 or later. + + ```diff title="package.json" + - "typescript": "^3.9.0" + + "typescript": "^4.0.0" + ``` + +### Patch Changes + +- [#4209](https://github.com/reactive/data-client/pull/4209) [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169) Thanks [@renovate](https://github.com/apps/renovate)! - Support `@babel/runtime` 8 + + Apps on Babel 8 now share their `@babel/runtime` with Data Client instead of installing a second copy. Apps on Babel 7 keep working unchanged. + +- [#4103](https://github.com/reactive/data-client/pull/4103) [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69) - Fix `controller.set()` types for Array schemas + + `controller.set([Entity], rows)` and `controller.set(new schema.Array(Entity), rows)` now typecheck. This writes every row in one store update: each row merges with its stored entity, and entities not in `rows` stay. This works with `exactOptionalPropertyTypes` on too. + + Rows are typed by the Entity's fields. The schema holds one Entity, [Union](https://dataclient.io/rest/api/Union) (for mixed types) or [Invalidate](https://dataclient.io/rest/api/Invalidate) (to delete), in an Array or [Values](https://dataclient.io/rest/api/Values) (which takes an object keyed by id). + + Batch `set()` needs `@data-client/rest` (or `endpoint`/`graphql`) from this release, since older Entity classes don't type as `EntityInterface`. + + ```ts + // Before: TypeScript error on [Ticker], so batches became one set() per row + for (const row of rows) { + ctrl.set(Ticker, { product_id: row.product_id }, row); + } + + // After: one store update + ctrl.set([Ticker], rows); + + // Mixed Entity types, batch deletes, and rows keyed by id + const Message = new schema.Union({ ticker: Ticker, trade: Trade }, 'type'); + ctrl.set([Message], messages); + ctrl.set([new schema.Invalidate(Ticker)], [{ product_id: 'BTC-USD' }]); + ctrl.set(new schema.Values(Ticker), { 'BTC-USD': row }); + ``` + +- [#4122](https://github.com/reactive/data-client/pull/4122) [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc) - Fix types for TypeScript 4.x when `skipLibCheck` is off + + TypeScript 4.0 through 4.7 no longer report `Cannot find name 'NoInfer'` from `@data-client/endpoint` or `@data-client/normalizr`, and TypeScript 4.0 through 4.9 no longer report `Only named exports may use 'export type'` from `@data-client/normalizr`. + + ```ts + import { Entity } from '@data-client/endpoint'; + import { normalize } from '@data-client/normalizr'; + + // Before (TypeScript 4.7, skipLibCheck: false): + // error TS2304: Cannot find name 'NoInfer'. + // error TS1383: Only named exports may use 'export type'. + // After: no errors + ``` + +- [#4019](https://github.com/reactive/data-client/pull/4019) [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e) Thanks [@renovate](https://github.com/apps/renovate)! - Fix TypeScript 7 module resolution for package exports + + TypeScript 7 requires a `types` condition in `package.json` `exports`. Without it, imports resolved to runtime entrypoints like `node.mjs` and lost declaration files. + ## 0.18.1 ### Patch Changes diff --git a/packages/normalizr/package.json b/packages/normalizr/package.json index 900bd43fab88..60fb91f5a345 100644 --- a/packages/normalizr/package.json +++ b/packages/normalizr/package.json @@ -1,6 +1,6 @@ { "name": "@data-client/normalizr", - "version": "0.18.1", + "version": "0.19.0", "description": "Normalizes and denormalizes JSON according to schema for Redux and Flux applications", "homepage": "https://dataclient.io/docs/concepts/normalization", "keywords": [ diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index e2299e51147b..19d55bbd1e3c 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,305 @@ # @data-client/react +## 0.19.0 + +### Minor Changes + +- [#4151](https://github.com/reactive/data-client/pull/4151) [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e) - BREAKING: Require TypeScript 4.0 or later + + The TypeScript 3.x type declarations are removed. They no longer type-checked on any TypeScript 3.x version, and + `@data-client/rest` already required TypeScript 4.0. Upgrade TypeScript to 4.0 or later. + + ```diff title="package.json" + - "typescript": "^3.9.0" + + "typescript": "^4.0.0" + ``` + +- [#4382](https://github.com/reactive/data-client/pull/4382) [`31f3ddb`](https://github.com/reactive/data-client/commit/31f3ddbc178ade2a7f59f7029a54c416df70e003) - BREAKING: [Manager.middleware](https://dataclient.io/docs/api/Manager#middleware) is required; `getMiddleware()` is removed + + A Manager without `middleware`, including one that still uses `getMiddleware()` (replaced in v0.14), is now a + TypeScript error, and throws in development when `DataProvider` or `DataClientPlugin` mounts. Rename `getMiddleware()` + to a `middleware` property: + + ```ts + // before + getMiddleware = (): Middleware => controller => next => async action => + next(action); + // after + middleware: Middleware = controller => next => async action => next(action); + ``` + +### Patch Changes + +- [#4407](https://github.com/reactive/data-client/pull/4407) [`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb) - Ship agent skills inside the packages + + Coding agents can now follow the skills for the version you have installed instead of guessing from older releases. Each package carries the skills it covers, and the new `data-client-skills` command (in `@data-client/react`, `vue`, `rest`, `graphql` and `endpoint`, so repos with only API definitions get it too) links them into `.agents/skills`, with `.claude/skills` linking to it, where Claude Code, Cursor and Codex load them as their own: + + ```bash + npx --no data-client-skills + ``` + + Commit the links. They point into `node_modules`, so they follow upgrades; run it again after adding, removing or upgrading `@data-client` packages to pick up new skills. [TanStack Intent](https://tanstack.com/intent) also finds these skills. + +- [#4209](https://github.com/reactive/data-client/pull/4209) [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169) Thanks [@renovate](https://github.com/apps/renovate)! - Support `@babel/runtime` 8 + + Apps on Babel 8 now share their `@babel/runtime` with Data Client instead of installing a second copy. Apps on Babel 7 keep working unchanged. + +- [#4103](https://github.com/reactive/data-client/pull/4103) [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69) - Fix `controller.set()` types for Array schemas + + `controller.set([Entity], rows)` and `controller.set(new schema.Array(Entity), rows)` now typecheck. This writes every row in one store update: each row merges with its stored entity, and entities not in `rows` stay. This works with `exactOptionalPropertyTypes` on too. + + Rows are typed by the Entity's fields. The schema holds one Entity, [Union](https://dataclient.io/rest/api/Union) (for mixed types) or [Invalidate](https://dataclient.io/rest/api/Invalidate) (to delete), in an Array or [Values](https://dataclient.io/rest/api/Values) (which takes an object keyed by id). + + Batch `set()` needs `@data-client/rest` (or `endpoint`/`graphql`) from this release, since older Entity classes don't type as `EntityInterface`. + + ```ts + // Before: TypeScript error on [Ticker], so batches became one set() per row + for (const row of rows) { + ctrl.set(Ticker, { product_id: row.product_id }, row); + } + + // After: one store update + ctrl.set([Ticker], rows); + + // Mixed Entity types, batch deletes, and rows keyed by id + const Message = new schema.Union({ ticker: Ticker, trade: Trade }, 'type'); + ctrl.set([Message], messages); + ctrl.set([new schema.Invalidate(Ticker)], [{ product_id: 'BTC-USD' }]); + ctrl.set(new schema.Values(Ticker), { 'BTC-USD': row }); + ``` + +- [#4230](https://github.com/reactive/data-client/pull/4230) [`46f1f24`](https://github.com/reactive/data-client/commit/46f1f24bcb04824805747ed2a1effe7baece337c) - Fix `controller.set()` types for a single [Invalidate](https://dataclient.io/rest/api/Invalidate) + + Deleting one entity with `set()` worked at runtime but failed to typecheck, since `Invalidate` isn't + [Queryable](https://dataclient.io/rest/api/schema#queryable). Pass the schema and the row to delete; the row is typed + by the Entity's fields. + + ```ts + // Before: TypeScript error, so a one-row batch was the workaround + ctrl.set([new Invalidate(Post)], [{ id: '5' }]); + + // After + ctrl.set(new Invalidate(Post), { id: '5' }); + ``` + + Like batch `set()`, it takes no `args` and no updater function. + +- [#4133](https://github.com/reactive/data-client/pull/4133) [`a82758c`](https://github.com/reactive/data-client/commit/a82758cd1998e58d7ad280407db28bd84f5d7b18) - Fix `controller.set()` accepting any value + + Values are now typed by the schema: Entities take their fields, while [Collection](https://dataclient.io/rest/api/Collection) + and [All](https://dataclient.io/rest/api/All) take a list of rows. [Query](https://dataclient.io/rest/api/Query) takes + the input of the schema it wraps, not what its `process()` returns. Updater functions must return the same. + + ```ts + // Before: these all typechecked, then failed or wrote nothing at runtime + ctrl.set(new schema.All(Todo), 42); + ctrl.set(TodoResource.getList.schema, 'anything'); + ctrl.set(Todo, { id: '5' }, { id: '5', completed: 'yes' }); + + // After: TypeScript errors on the above; these typecheck + ctrl.set(TodoResource.getList.schema, [{ id: '5', completed: true }]); + ctrl.set(new schema.All(Todo), [{ id: '5', completed: true }]); + ``` + + When each member declares its discriminator as a literal (like `readonly type = 'post'`), a + [Union](https://dataclient.io/rest/api/Union) row is checked against the member it selects. Only + declared fields are accepted, so a key read by a `schemaAttribute` function must be declared on each member. + + ```ts + const Feed = new schema.Union({ post: Post, comment: Comment }, 'type'); + // TypeScript error: commentBody is a Comment field, not a Post field + ctrl.set( + Feed, + { id: '1', type: 'post' }, + { type: 'post', commentBody: 'hi' }, + ); + ``` + +- [#4228](https://github.com/reactive/data-client/pull/4228) [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee) - Fix TypeScript error passing a `Controller` subclass to `DataProvider` or `DataClientPlugin` + + A plain `class MyController extends Controller` failed to typecheck as the `Controller` option of [DataProvider](https://dataclient.io/docs/api/DataProvider#Controller), Vue's [DataClientPlugin](https://dataclient.io/vue/api/DataClientPlugin#Controller), and the `@data-client/react/redux` `DataProvider`, so the documented example needed a cast. `MockController()` from `@data-client/core/mock` had the same error when wrapping your subclass. These now typecheck, and you can drop the casts. + + ```tsx + class MyController extends Controller { + doSomething = () => console.log('hi'); + } + + // Before: TypeScript error, so you had to cast + + app.use(DataClientPlugin, { Controller: MyController as typeof Controller }); + + // After + + app.use(DataClientPlugin, { Controller: MyController }); + ``` + +- [#4420](https://github.com/reactive/data-client/pull/4420) [`c3b8c54`](https://github.com/reactive/data-client/commit/c3b8c54bc3062cf082e67c215310cb98b3a03078) - Fix fixture types needing `@data-client/endpoint` installed + + `Fixture` and the other fixture types from `@data-client/react/mock`, `@data-client/core/mock` and `@data-client/test` no + longer resolve `@data-client/endpoint`, which those packages don't depend on. Projects that install only + `@data-client/react` and `@data-client/test` (for example with pnpm's strict layout) no longer get + `Cannot find module '@data-client/endpoint'` when type-checking fixtures. + +- [#4150](https://github.com/reactive/data-client/pull/4150) [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2) - Fix `useCache()` and `useDLE()` returning a truthy `Symbol` for deleted entities + + After an entity was deleted and its refetch failed, `useCache()` and `useDLE()` (React and Vue) returned an internal + `Symbol` instead of `undefined`. Since a `Symbol` is truthy, "not loaded" checks passed, and code went on to use it as + the entity: + + ```tsx + const todo = useCache(TodoResource.get, { id }); + if (!todo) return ; + // Before: reached here with a Symbol; todo.title was undefined and todo.title.trim() threw + // After: the placeholder renders + return ; + ``` + + [Controller.getResponse()](https://dataclient.io/docs/api/Controller#getResponse) and + [Controller.fetchIfStale()](https://dataclient.io/docs/api/Controller#fetchIfStale) now also give `undefined` there, + like [Controller.get()](https://dataclient.io/docs/api/Controller#get) already did. + +- [#4393](https://github.com/reactive/data-client/pull/4393) [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23) - Add recent actions to `globalThis.__DC_ACTIONS__` in development + + Coding agents and console debugging can now see what each store dispatched, including the fetches made while the + page loaded, without the Redux DevTools extension. [DevToolsManager](https://dataclient.io/docs/api/DevToolsManager#controllers) + keeps each store's recent actions in a `Map` keyed like `__DC_CONTROLLERS__`. Production builds don't include it. + + To keep memory small, only the newest 20 actions keep their payloads, and each polling key (endpoint and args) keeps + only its last two polls (`maxPollingActions`, default 4 actions). + + ```js title="Browser DevTools console" + __DC_ACTIONS__.get('Data Client: My App').slice(-10); + ``` + +- [#4163](https://github.com/reactive/data-client/pull/4163) [`159c963`](https://github.com/reactive/data-client/commit/159c9633679d95427fe4f626aec341c76e4578f8) - Fix slow updates in development while Redux DevTools is open + + With the [Redux DevTools](https://dataclient.io/docs/getting-started/debugging) extension open, every store update + stalled the page while DevTools serialized the store: about 20ms with 50 entities, and 200ms with 500. Apps doing + many `controller.set()` calls, polling, or live updates would stutter in development. Each update now serializes + 40-60x faster, and timestamps still show as readable times like `10:42:07.123 AM`. + +- [#4393](https://github.com/reactive/data-client/pull/4393) [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23) - Fix stores with the same devtools name hiding each other in `__DC_CONTROLLERS__` + + With two `DataProvider`s, or two Vue apps using `DataClientPlugin`, on one page and the default devtools name, the + second store replaced the first in `globalThis.__DC_CONTROLLERS__`, so debugging tools and coding agents could only find one. The second now + registers as `'Data Client: My App (2)'`, the next as `(3)`, and so on. + +- [#4227](https://github.com/reactive/data-client/pull/4227) [`47502c6`](https://github.com/reactive/data-client/commit/47502c664df913297fba3e5011a975dfd01c0d8d) - Type FETCH `action.meta.promise` as `Promise` + + Managers can now call `.finally()` and `.catch()` on a FETCH action's `meta.promise` without a TypeScript error. It was always a real `Promise` at runtime, but was typed `PromiseLike`, which only has `.then()`. + + ```ts + // Before: TypeScript error on .finally(), so both callbacks went to .then() + const track = () => + trackTiming(action.endpoint.name, performance.now() - start); + action.meta.promise.then(track, track); + + // After + action.meta.promise + .finally(() => { + trackTiming(action.endpoint.name, performance.now() - start); + }) + // the fetch's caller handles errors; this only observes timing + .catch(() => {}); + ``` + +- [#4250](https://github.com/reactive/data-client/pull/4250) [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a) - Fixture `args` accept readonly tuples + + Fixtures written with `args: [...] as const` now type-check when passed to [MockResolver](https://dataclient.io/docs/api/MockResolver), `renderDataHook()`, Vue's `renderDataCompose()` or `mockInitialState()`. Before, TypeScript rejected them with "The type 'readonly [...]' is 'readonly' and cannot be assigned to the mutable type", so you had to drop `as const` or cast. + + ```ts + const fixtures = [ + { + endpoint: TodoResource.getList, + args: [{ userId: 1 }] as const, + response: [{ id: 1, title: 'Write tests', userId: 1 }], + }, + ]; + + // Before: type error on `fixtures`. After: works as written + + + ; + ``` + +- [#4232](https://github.com/reactive/data-client/pull/4232) [`31b1820`](https://github.com/reactive/data-client/commit/31b182033106d5ce44352481577d3c321e39ebe9) - Fix `',' expected` errors on TypeScript 4.0 through 4.4 + + Importing `@data-client/react/redux`, `@data-client/react/nextjs` or `@data-client/test` failed to compile on TypeScript before 4.5, even with `skipLibCheck` on, because their declaration files used syntax those versions can't parse. They now compile on TypeScript 4.0 and later. + + ```ts + import { DataProvider } from '@data-client/react/nextjs'; + import { renderDataHook } from '@data-client/test'; + + // Before (TypeScript 4.0 to 4.4): + // node_modules/@data-client/react/lib/server/nextjs/DataProvider/DataProvider.d.ts(1,15): error TS1005: ',' expected. + // node_modules/@data-client/test/lib/makeRenderDataClient/index.d.ts(3,33): error TS1005: ',' expected. + // After: no errors + ``` + + `@data-client/vue/test` types now also resolve with `moduleResolution: "node"`. + +- [#4122](https://github.com/reactive/data-client/pull/4122) [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc) - Fix types for TypeScript 4.x when `skipLibCheck` is off + + TypeScript 4.0 through 4.7 no longer report `Cannot find name 'NoInfer'` from `@data-client/endpoint` or `@data-client/normalizr`, and TypeScript 4.0 through 4.9 no longer report `Only named exports may use 'export type'` from `@data-client/normalizr`. + + ```ts + import { Entity } from '@data-client/endpoint'; + import { normalize } from '@data-client/normalizr'; + + // Before (TypeScript 4.7, skipLibCheck: false): + // error TS2304: Cannot find name 'NoInfer'. + // error TS1383: Only named exports may use 'export type'. + // After: no errors + ``` + +- [#4378](https://github.com/reactive/data-client/pull/4378) [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53) - Clear error for a [Manager](https://dataclient.io/docs/api/Manager) without `middleware` + + A Manager must define [middleware](https://dataclient.io/docs/api/Manager#middleware). One without it used to crash + with `manager.middleware is not a function`; in development it now throws an error naming the Manager and linking to + the docs. + +- [#4378](https://github.com/reactive/data-client/pull/4378) [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53) - Fix React Native screens refetching fresh data every time they regain focus + + On React Native, [useSuspense()](https://dataclient.io/docs/api/useSuspense), [useFetch()](https://dataclient.io/docs/api/useFetch) + and [useDLE()](https://dataclient.io/docs/api/useDLE) revalidate when a screen comes back into focus. They checked + the expiry from the screen's first render, so once that data went stale, every refocus refetched it, even right after + a fetch had made it fresh. After the arguments changed, they could also refetch the old arguments. + + Refocusing now refetches only when the current data is [stale](https://dataclient.io/docs/concepts/expiry-policy#stale) + or [invalid](https://dataclient.io/docs/concepts/expiry-policy#invalid), using the current arguments. + +- [#4238](https://github.com/reactive/data-client/pull/4238) [`954b1e9`](https://github.com/reactive/data-client/commit/954b1e9041ba47b39b9ffdd53a55b0b16adc8675) - Fix TypeScript error passing `prepareStore()`'s store to react-redux's `` + + `prepareStore()` from `@data-client/react/redux` typed its `store` as a minimal object with only `getState()` and `subscribe()`, so [using it with React-Redux](https://dataclient.io/docs/guides/redux) needed a cast, and `store.dispatch()` was a TypeScript error. It's now typed as a Redux `Store`. Its `replaceReducer()` and `[Symbol.observable]()` aren't supported: they throw, and are typed as returning `never`. + + ```tsx + const { store, selector, controller } = prepareStore( + initialState, + managers, + Controller, + otherReducers, + extraMiddlewares, + ); + + // Before: TypeScript error, so you had to cast + + + // After + + ``` + +- [#4355](https://github.com/reactive/data-client/pull/4355) [`4829b10`](https://github.com/reactive/data-client/commit/4829b1033a24f52e2a1d0e5a03532f9cfa4f525f) - Support React Native 0.87 + + React Native 0.87 removed `InteractionManager`, so apps on it crashed as soon as a component called `useSuspense()`, `useFetch()` or `useDLE()`. On 0.87 and later, Data Client now waits for idle time with `requestIdleCallback()`, as React Native recommends. Older React Native versions keep using `InteractionManager`. + +- [#4019](https://github.com/reactive/data-client/pull/4019) [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e) Thanks [@renovate](https://github.com/apps/renovate)! - Fix TypeScript 7 module resolution for package exports + + TypeScript 7 requires a `types` condition in `package.json` `exports`. Without it, imports resolved to runtime entrypoints like `node.mjs` and lost declaration files. + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`46f1f24`](https://github.com/reactive/data-client/commit/46f1f24bcb04824805747ed2a1effe7baece337c), [`a82758c`](https://github.com/reactive/data-client/commit/a82758cd1998e58d7ad280407db28bd84f5d7b18), [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee), [`c3b8c54`](https://github.com/reactive/data-client/commit/c3b8c54bc3062cf082e67c215310cb98b3a03078), [`b1d40fd`](https://github.com/reactive/data-client/commit/b1d40fd80c9aa292f5cdbce9b573e7749d889069), [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`159c963`](https://github.com/reactive/data-client/commit/159c9633679d95427fe4f626aec341c76e4578f8), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`47502c6`](https://github.com/reactive/data-client/commit/47502c664df913297fba3e5011a975dfd01c0d8d), [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a), [`31f3ddb`](https://github.com/reactive/data-client/commit/31f3ddbc178ade2a7f59f7029a54c416df70e003), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/core@0.19.0 + - @data-client/use-enhanced-reducer@0.1.15 + ## 0.18.1 ### Patch Changes diff --git a/packages/react/package.json b/packages/react/package.json index 5758f31d63d0..f4bbac957477 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@data-client/react", - "version": "0.18.1", + "version": "0.19.0", "description": "Async State Management without the Management. REST, GraphQL, SSE, Websockets, Fetch", "homepage": "https://dataclient.io", "repository": { diff --git a/packages/rest/CHANGELOG.md b/packages/rest/CHANGELOG.md index 97852fc799b3..83c8bf495a3a 100644 --- a/packages/rest/CHANGELOG.md +++ b/packages/rest/CHANGELOG.md @@ -1,5 +1,236 @@ # @data-client/rest +## 0.19.0 + +### Patch Changes + +- [#4407](https://github.com/reactive/data-client/pull/4407) [`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb) - Ship agent skills inside the packages + + Coding agents can now follow the skills for the version you have installed instead of guessing from older releases. Each package carries the skills it covers, and the new `data-client-skills` command (in `@data-client/react`, `vue`, `rest`, `graphql` and `endpoint`, so repos with only API definitions get it too) links them into `.agents/skills`, with `.claude/skills` linking to it, where Claude Code, Cursor and Codex load them as their own: + + ```bash + npx --no data-client-skills + ``` + + Commit the links. They point into `node_modules`, so they follow upgrades; run it again after adding, removing or upgrading `@data-client` packages to pick up new skills. [TanStack Intent](https://tanstack.com/intent) also finds these skills. + +- [#4209](https://github.com/reactive/data-client/pull/4209) [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169) Thanks [@renovate](https://github.com/apps/renovate)! - Support `@babel/runtime` 8 + + Apps on Babel 8 now share their `@babel/runtime` with Data Client instead of installing a second copy. Apps on Babel 7 keep working unchanged. + +- [#4149](https://github.com/reactive/data-client/pull/4149) [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e) - Fix Entity classes not assignable to `EntityInterface` + + [Entity.pk()](https://dataclient.io/rest/api/Entity#pk)'s static `args` parameter is now `readonly any[]`, matching `EntityInterface`. Entity classes can be passed where an `EntityInterface` is expected. + + ```ts + import type { EntityInterface } from '@data-client/react'; + + // Before: TypeScript error (args is readonly in EntityInterface) + // After: typechecks + const schema: EntityInterface = User; + ``` + + Overrides of `static pk()` that type `args` as a mutable array still compile, but a future breaking release will require `readonly any[]`, so update them now: + + ```ts + class User extends Entity { + static pk(value: any, parent?: any, key?: string, args?: readonly any[]) { + return `${value.id}-${args?.[0]?.org}`; + } + } + ``` + +- [#4183](https://github.com/reactive/data-client/pull/4183) [`a73b437`](https://github.com/reactive/data-client/commit/a73b437c8f60ef8c64266874ea82e5119dfe4874) - Type the `params` and `body` that `process()` receives in `RestEndpoint` options + + A `process(value, params)` method passed to `new RestEndpoint()`, `RestEndpoint.extend()` or `resource().extend()` used to get `params` typed as `any`, so a typo or a wrong assumption about a path parameter went unnoticed until runtime. They are now typed from the endpoint's `path`, `searchParams` and `body`, including a `path` set in the same `.extend()` call. + + ```ts + const getUser = new RestEndpoint({ path: '/users/:id' }); + + const getUserById = getUser.extend({ + path: '/users/by-id/:userId', + process(value, params) { + params.userId; // string | number + params.id; // TypeScript error: 'id' is not a param of '/users/by-id/:userId' + return value; + }, + }); + ``` + + Endpoints whose params are optional pass `params` as possibly `undefined`, so read it with `params?.page`. + + This can surface new TypeScript errors in existing `process()` methods that read a param the endpoint doesn't have, or that read optional `params` without a check. Each is a read that could be `undefined` or throw at runtime, so fix the param name or add the check. + + On TypeScript 5.x and earlier, `process(value, params)` in an `.extend()` that also sets `path` no longer fails with "implicitly has an 'any' type" under `strict`. + +- [#4173](https://github.com/reactive/data-client/pull/4173) [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7) - Speed up TypeScript checking of `RestEndpoint`, `resource()` and `.extend()` + + Editors and `tsc` check code that defines or calls endpoints faster and with less memory. In our stress tests, a file of 150 RestEndpoints with long paths, `.extend()` and `.paginated()` checked in about half the time (3.1s → 1.6s) and memory (345MB → 207MB). Files that use `resource()` with React or Vue hooks did 22-25% less type work. TypeScript reports the same errors as before. + + On TypeScript 5.x and earlier, a `process(value, params)` method passed to `.extend()` no longer fails with "implicitly has an 'any' type" under `strict`, matching TypeScript 6+. TypeScript 4.0 also accepts a chained `.extend().extend()`. + + ```ts + const getUser = new RestEndpoint({ path: '/users/:id', schema: User }); + + // Before (TypeScript 5.x and earlier): error TS7006: Parameter 'value' implicitly has an 'any' type. + // After: no error + const getUserName = getUser.extend({ + process(value, params) { + return value.name; + }, + }); + ``` + +- [#4122](https://github.com/reactive/data-client/pull/4122) [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc) - Fix more TypeScript 4.x errors when `skipLibCheck` is off + + [Entity](https://dataclient.io/rest/api/Entity), [Endpoint](https://dataclient.io/rest/api/Endpoint), [Union](https://dataclient.io/rest/api/Union) and [RestEndpoint](https://dataclient.io/rest/api/RestEndpoint) declarations no longer report errors on TypeScript 4.0 through 4.5. On TypeScript 4.0 and 4.1, an `Entity` can be an `Endpoint` schema again. + + ```ts + import { Endpoint, Entity, schema } from '@data-client/endpoint'; + + class User extends Entity { + id = ''; + type = 'users'; + } + const getUser = new Endpoint( + (id: string) => fetch(`/users/${id}`).then(res => res.json()), + { schema: User }, + ); + const feed = new schema.Union({ users: User }, 'type'); + + // Before (TypeScript 4.0, skipLibCheck: false): + // error TS2456: Type alias 'RemoveArray' circularly references itself. + // error TS2322: Type 'typeof User' is not assignable to type 'EntityInterface'. + // Before (TypeScript 4.2): + // error TS2344: Type 'TBase' does not satisfy the constraint 'new (...args: any) => any'. + // After: no errors + ``` + +- [#4122](https://github.com/reactive/data-client/pull/4122) [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc) - Fix types for TypeScript 4.x when `skipLibCheck` is off + + TypeScript 4.0 through 4.7 no longer report `Cannot find name 'NoInfer'` from `@data-client/endpoint` or `@data-client/normalizr`, and TypeScript 4.0 through 4.9 no longer report `Only named exports may use 'export type'` from `@data-client/normalizr`. + + ```ts + import { Entity } from '@data-client/endpoint'; + import { normalize } from '@data-client/normalizr'; + + // Before (TypeScript 4.7, skipLibCheck: false): + // error TS2304: Cannot find name 'NoInfer'. + // error TS1383: Only named exports may use 'export type'. + // After: no errors + ``` + +- [#4224](https://github.com/reactive/data-client/pull/4224) [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176) - Fix `Entity.maxEntityDepth` docs: the default is 64, not 128 + + Editor hover docs for `static maxEntityDepth` now show the real default. Runtime behavior is unchanged; set `maxEntityDepth` explicitly if you relied on 128. + +- [#4198](https://github.com/reactive/data-client/pull/4198) [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336) - Fix `getOptimisticResponse()` accepting any return value + + Unless an endpoint has a typed `process()`, its [getOptimisticResponse()](https://dataclient.io/rest/api/RestEndpoint#getoptimisticresponse) + could return anything, so a wrong field type only showed up as bad data in the UI until the server responded. The return + value is now checked against the endpoint's schema, like a [Controller.set()](https://dataclient.io/docs/api/Controller#set) + value: an Entity takes any of its fields, and a [Collection](https://dataclient.io/rest/api/Collection) takes a list of them. + This applies to `new RestEndpoint()`, `.extend()` and `resource().extend()`. + + ```ts + const toggleTodo = new RestEndpoint({ + path: '/todos/:id', + method: 'PATCH', + schema: Todo, + getOptimisticResponse(snap, { id }) { + const todo = snap.get(Todo, { id }); + if (!todo) throw snap.abort; + // Before: compiled, then the checkbox stayed checked because 'false' is truthy + // After: TypeScript error, completed is a boolean + return { id, completed: todo.completed ? 'false' : 'true' }; + }, + }); + ``` + + Return the field's real type instead (`completed: !todo.completed`). Endpoints with a typed `process()` keep checking + the return against what `process()` returns. + +- [#4226](https://github.com/reactive/data-client/pull/4226) [`643d818`](https://github.com/reactive/data-client/commit/643d818ac757a0218e91d9523879e25024c5e61f) - Fix `RestEndpoint.push`, `unshift` and `remove` body types when a `Query` or `Lazy` wraps the endpoint's `Collection` + + Sorting or filtering a list with a [Query](https://dataclient.io/rest/api/Query) around its [Collection](https://dataclient.io/rest/api/Collection) made `getPosts.push` reject every body except `FormData`, though it adds to the list at runtime. The body is now typed from the Collection's Entity, so a correct body compiles and a wrong field is a TypeScript error. The same applies to a Collection wrapped in [Lazy](https://dataclient.io/rest/api/Lazy). + + ```ts + const getPosts = new RestEndpoint({ + path: '/:group/posts', + searchParams: {} as { orderBy?: string }, + schema: new Query( + new Collection([Post], { nonFilterArgumentKeys: /orderBy/ }), + (posts, { orderBy } = {}) => sortBy(posts, orderBy), + ), + }); + ``` + + If you cast the body to get past this error, the cast can go: + + ```ts + // Before + ctrl.fetch(getPosts.push, { group: 'react' }, { title, author } as any); + // After + ctrl.fetch(getPosts.push, { group: 'react' }, { title, author }); + ``` + +- [#4235](https://github.com/reactive/data-client/pull/4235) [`588a558`](https://github.com/reactive/data-client/commit/588a558332d9d2bc6a313b2f4b6700bb3ff017f2) - Fix TypeScript error passing `FormData` to `resource().create` + + `resource().create` sends a `FormData` body as-is, the same as `update`, `partialUpdate` and + `getList.push`, but its type only allowed an object, so submitting a form needed a cast. This now typechecks, + and you can drop the cast. `create` is deprecated, and its replacement `getList.push` takes `FormData` too. + + ```tsx + { + e.preventDefault(); + // Before: TypeScript error, so you had to cast + ctrl.fetch(PostResource.create, new FormData(e.currentTarget) as any); + // After + ctrl.fetch(PostResource.create, new FormData(e.currentTarget)); + }} + > + ``` + +- [#4184](https://github.com/reactive/data-client/pull/4184) [`bf377f4`](https://github.com/reactive/data-client/commit/bf377f46a2c916d8e808472645f1da9704ffaf91) - Fix `resource().extend({ get: ... })` dropping endpoints added earlier from its type + + Customizing a resource's standard endpoints with `.extend({ ... })` kept every endpoint at runtime, but TypeScript lost the ones added before it with `.extend('name', options)`, and the deprecated `create`. Using them was a type error even though they worked. + + ```ts + const UserResource = resource({ path: '/users/:id', schema: User }) + .extend('current', { path: '/user' }) + .extend({ get: { dataExpiryLength: 60000 } }); + + // Before: Property 'current' does not exist + // After: no error + const me = await ctrl.fetch(UserResource.current); + ``` + +- [#4262](https://github.com/reactive/data-client/pull/4262) [`ae7080d`](https://github.com/reactive/data-client/commit/ae7080de64ca8621833a71267ec84d2a9d5e19dd) - Fix pushing several items at once sending `"[object Object]"` instead of JSON + + [RestEndpoint.push](https://dataclient.io/rest/api/RestEndpoint#push), `unshift` and `remove` accept an array of items, + but sent it to `fetch()` as-is, so the server received `"[object Object],[object Object]"` with no JSON `Content-Type`. Arrays are + now JSON-encoded like objects, with `Content-Type: application/json`. `FormData`, `Blob`, `URLSearchParams` and strings + still go to `fetch()` unchanged. + + `resource().create` takes the same bodies as `getList.push`, including an array. + + ```ts + // Before: the server received "[object Object],[object Object]" + // After: the server receives [{"title":"Buy milk"},{"title":"Walk dog"}] + await ctrl.fetch(TodoResource.getList.push, [ + { title: 'Buy milk' }, + { title: 'Walk dog' }, + ]); + ``` + +- [#4019](https://github.com/reactive/data-client/pull/4019) [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e) Thanks [@renovate](https://github.com/apps/renovate)! - Fix TypeScript 7 module resolution for package exports + + TypeScript 7 requires a `types` condition in `package.json` `exports`. Without it, imports resolved to runtime entrypoints like `node.mjs` and lost declaration files. + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`cc57a77`](https://github.com/reactive/data-client/commit/cc57a77d2e563071926f50cb9054516d2ab9101e), [`022f449`](https://github.com/reactive/data-client/commit/022f44950bf687b61f2d349e42ab906071c6fce7), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`a403df8`](https://github.com/reactive/data-client/commit/a403df8f22dadb0dbd9a6cf72a65f9187ae63176), [`cb6d9f2`](https://github.com/reactive/data-client/commit/cb6d9f21ae73ab79ac5f1d6aea04f68d7c2c6336), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/endpoint@0.19.0 + ## 0.18.1 ### Patch Changes diff --git a/packages/rest/package.json b/packages/rest/package.json index b2daa7aec472..3a7263d4eaf5 100644 --- a/packages/rest/package.json +++ b/packages/rest/package.json @@ -1,6 +1,6 @@ { "name": "@data-client/rest", - "version": "0.18.1", + "version": "0.19.0", "description": "Quickly define typed REST resources and endpoints", "homepage": "https://dataclient.io/rest", "repository": { diff --git a/packages/test/CHANGELOG.md b/packages/test/CHANGELOG.md index 0a4a4d01c311..78200a92277e 100644 --- a/packages/test/CHANGELOG.md +++ b/packages/test/CHANGELOG.md @@ -1,5 +1,127 @@ # @data-client/test +## 0.19.0 + +### Minor Changes + +- [#4151](https://github.com/reactive/data-client/pull/4151) [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e) - BREAKING: Require TypeScript 4.0 or later + + The TypeScript 3.x type declarations are removed. They no longer type-checked on any TypeScript 3.x version, and + `@data-client/rest` already required TypeScript 4.0. Upgrade TypeScript to 4.0 or later. + + ```diff title="package.json" + - "typescript": "^3.9.0" + + "typescript": "^4.0.0" + ``` + +- [#4414](https://github.com/reactive/data-client/pull/4414) [`38acf12`](https://github.com/reactive/data-client/commit/38acf129ac4a3ed2a15167ab5818cdf53290f45b) - BREAKING: `@data-client/test` requires `@data-client/react` 0.15.3 or later + + Support for `@data-client/react` 0.12 through 0.15.2 is dropped, since `@data-client/test` imports + `@data-client/react/mock`, which first loads in Jest and other CommonJS tests in 0.15.3. Upgrade `@data-client/react` + along with `@data-client/test`. + + ```diff title="package.json" + - "@data-client/react": "^0.14.0", + + "@data-client/react": "^0.19.0", + ``` + + `Fixture`, `Interceptor`, and the other fixture types from `@data-client/test` are now the same types that + `@data-client/react/mock` exports, so fixtures typed with either import work everywhere. + +### Patch Changes + +- [#4209](https://github.com/reactive/data-client/pull/4209) [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169) Thanks [@renovate](https://github.com/apps/renovate)! - Support `@babel/runtime` 8 + + Apps on Babel 8 now share their `@babel/runtime` with Data Client instead of installing a second copy. Apps on Babel 7 keep working unchanged. + +- [#4228](https://github.com/reactive/data-client/pull/4228) [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee) - Fix TypeScript error passing a `Controller` subclass to `DataProvider` or `DataClientPlugin` + + A plain `class MyController extends Controller` failed to typecheck as the `Controller` option of [DataProvider](https://dataclient.io/docs/api/DataProvider#Controller), Vue's [DataClientPlugin](https://dataclient.io/vue/api/DataClientPlugin#Controller), and the `@data-client/react/redux` `DataProvider`, so the documented example needed a cast. `MockController()` from `@data-client/core/mock` had the same error when wrapping your subclass. These now typecheck, and you can drop the casts. + + ```tsx + class MyController extends Controller { + doSomething = () => console.log('hi'); + } + + // Before: TypeScript error, so you had to cast + + app.use(DataClientPlugin, { Controller: MyController as typeof Controller }); + + // After + + app.use(DataClientPlugin, { Controller: MyController }); + ``` + +- [#4420](https://github.com/reactive/data-client/pull/4420) [`c3b8c54`](https://github.com/reactive/data-client/commit/c3b8c54bc3062cf082e67c215310cb98b3a03078) - Fix fixture types needing `@data-client/endpoint` installed + + `Fixture` and the other fixture types from `@data-client/react/mock`, `@data-client/core/mock` and `@data-client/test` no + longer resolve `@data-client/endpoint`, which those packages don't depend on. Projects that install only + `@data-client/react` and `@data-client/test` (for example with pnpm's strict layout) no longer get + `Cannot find module '@data-client/endpoint'` when type-checking fixtures. + +- [#4250](https://github.com/reactive/data-client/pull/4250) [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a) - Fixture `args` accept readonly tuples + + Fixtures written with `args: [...] as const` now type-check when passed to [MockResolver](https://dataclient.io/docs/api/MockResolver), `renderDataHook()`, Vue's `renderDataCompose()` or `mockInitialState()`. Before, TypeScript rejected them with "The type 'readonly [...]' is 'readonly' and cannot be assigned to the mutable type", so you had to drop `as const` or cast. + + ```ts + const fixtures = [ + { + endpoint: TodoResource.getList, + args: [{ userId: 1 }] as const, + response: [{ id: 1, title: 'Write tests', userId: 1 }], + }, + ]; + + // Before: type error on `fixtures`. After: works as written + + + ; + ``` + +- [#4232](https://github.com/reactive/data-client/pull/4232) [`31b1820`](https://github.com/reactive/data-client/commit/31b182033106d5ce44352481577d3c321e39ebe9) - Fix `',' expected` errors on TypeScript 4.0 through 4.4 + + Importing `@data-client/react/redux`, `@data-client/react/nextjs` or `@data-client/test` failed to compile on TypeScript before 4.5, even with `skipLibCheck` on, because their declaration files used syntax those versions can't parse. They now compile on TypeScript 4.0 and later. + + ```ts + import { DataProvider } from '@data-client/react/nextjs'; + import { renderDataHook } from '@data-client/test'; + + // Before (TypeScript 4.0 to 4.4): + // node_modules/@data-client/react/lib/server/nextjs/DataProvider/DataProvider.d.ts(1,15): error TS1005: ',' expected. + // node_modules/@data-client/test/lib/makeRenderDataClient/index.d.ts(3,33): error TS1005: ',' expected. + // After: no errors + ``` + + `@data-client/vue/test` types now also resolve with `moduleResolution: "node"`. + +- [#4099](https://github.com/reactive/data-client/pull/4099) [`4ae6080`](https://github.com/reactive/data-client/commit/4ae608081ed33c6ce5ab3c0032276cc3069311f8) - Fix mount effects when `renderDataHook()` suspends on the first render + + `renderDataHook()` and `makeRenderDataHook()` now run provider mount effects when the first render suspends, including `use(useFetch())`. The hook result stays unresolved until the data arrives. + +- [#4251](https://github.com/reactive/data-client/pull/4251) [`dc84c02`](https://github.com/reactive/data-client/commit/dc84c02853fd4adafd79c1c96636c259df04abf7) - Fix `act` and `renderHook` typed as `any` on TypeScript 4.0–4.4 + + `act()`, `renderHook()` and `RenderHookOptions` from `@data-client/test` were `any` on TypeScript 4.0–4.4, and + reported `Cannot find module './renderHook.cjs'` with `skipLibCheck` off. They now have their real types: + + ```ts + import { act, renderHook } from '@data-client/test'; + + const { result } = renderHook(() => 5); + result.current; // number + await act(() => Promise.resolve(5)); // number + ``` + +- [#4374](https://github.com/reactive/data-client/pull/4374) [`274fc07`](https://github.com/reactive/data-client/commit/274fc0795105bb3ece3ec6b9966dc03b14bbac36) Thanks [@renovate](https://github.com/apps/renovate)! - Support React Native Testing Library 14 + + [renderDataHook()](https://dataclient.io/docs/api/renderDataHook) keeps working on React Native after upgrading to `@testing-library/react-native` 14, and stays synchronous, so existing `renderDataHook()` calls need no `await`. Install `test-renderer`, which RNTL 14 needs anyway. Projects on RNTL 13 keep working unchanged. + +- [#4019](https://github.com/reactive/data-client/pull/4019) [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e) Thanks [@renovate](https://github.com/apps/renovate)! - Fix TypeScript 7 module resolution for package exports + + TypeScript 7 requires a `types` condition in `package.json` `exports`. Without it, imports resolved to runtime entrypoints like `node.mjs` and lost declaration files. + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`46f1f24`](https://github.com/reactive/data-client/commit/46f1f24bcb04824805747ed2a1effe7baece337c), [`a82758c`](https://github.com/reactive/data-client/commit/a82758cd1998e58d7ad280407db28bd84f5d7b18), [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee), [`c3b8c54`](https://github.com/reactive/data-client/commit/c3b8c54bc3062cf082e67c215310cb98b3a03078), [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`159c963`](https://github.com/reactive/data-client/commit/159c9633679d95427fe4f626aec341c76e4578f8), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`47502c6`](https://github.com/reactive/data-client/commit/47502c664df913297fba3e5011a975dfd01c0d8d), [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a), [`31b1820`](https://github.com/reactive/data-client/commit/31b182033106d5ce44352481577d3c321e39ebe9), [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc), [`31f3ddb`](https://github.com/reactive/data-client/commit/31f3ddbc178ade2a7f59f7029a54c416df70e003), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`954b1e9`](https://github.com/reactive/data-client/commit/954b1e9041ba47b39b9ffdd53a55b0b16adc8675), [`4829b10`](https://github.com/reactive/data-client/commit/4829b1033a24f52e2a1d0e5a03532f9cfa4f525f), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/react@0.19.0 + ## 0.18.0 ### Patch Changes diff --git a/packages/test/package.json b/packages/test/package.json index 620cb83f4170..47c33c0b764f 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -1,6 +1,6 @@ { "name": "@data-client/test", - "version": "0.18.0", + "version": "0.19.0", "description": "Testing utilities for Data Client", "homepage": "https://dataclient.io/docs/guides/storybook", "repository": { @@ -109,7 +109,7 @@ "@testing-library/react": "^16.0.0" }, "peerDependencies": { - "@data-client/react": "^0.15.3 || ^0.16.0 || ^0.17.0 || ^0.18.0", + "@data-client/react": "^0.19.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/react-native": "^13.0.0 || ^14.0.0", "@types/react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-0 || ^19.0.0", diff --git a/packages/use-enhanced-reducer/CHANGELOG.md b/packages/use-enhanced-reducer/CHANGELOG.md index e70360c37905..fe96727157bc 100644 --- a/packages/use-enhanced-reducer/CHANGELOG.md +++ b/packages/use-enhanced-reducer/CHANGELOG.md @@ -1,5 +1,13 @@ # @data-client/use-enhanced-reducer +## 0.1.15 + +### Patch Changes + +- [#4209](https://github.com/reactive/data-client/pull/4209) [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169) Thanks [@renovate](https://github.com/apps/renovate)! - Support `@babel/runtime` 8 + + Apps on Babel 8 now share their `@babel/runtime` with Data Client instead of installing a second copy. Apps on Babel 7 keep working unchanged. + ## 0.1.14 ### Patch Changes diff --git a/packages/use-enhanced-reducer/package.json b/packages/use-enhanced-reducer/package.json index 376ae2019bc5..7387d0f0e448 100644 --- a/packages/use-enhanced-reducer/package.json +++ b/packages/use-enhanced-reducer/package.json @@ -1,6 +1,6 @@ { "name": "@data-client/use-enhanced-reducer", - "version": "0.1.14", + "version": "0.1.15", "description": "Add powerful orchestration to hooks-based Flux stores", "homepage": "https://github.com/reactive/data-client/tree/master/packages/use-enhanced-reducer#readme", "repository": { diff --git a/packages/vue/CHANGELOG.md b/packages/vue/CHANGELOG.md index 0e98e16ab9b1..d98584237b4a 100644 --- a/packages/vue/CHANGELOG.md +++ b/packages/vue/CHANGELOG.md @@ -1,5 +1,457 @@ # @data-client/vue +## 0.19.0 + +### Minor Changes + +- [#4382](https://github.com/reactive/data-client/pull/4382) [`31f3ddb`](https://github.com/reactive/data-client/commit/31f3ddbc178ade2a7f59f7029a54c416df70e003) - BREAKING: [Manager.middleware](https://dataclient.io/docs/api/Manager#middleware) is required; `getMiddleware()` is removed + + A Manager without `middleware`, including one that still uses `getMiddleware()` (replaced in v0.14), is now a + TypeScript error, and throws in development when `DataProvider` or `DataClientPlugin` mounts. Rename `getMiddleware()` + to a `middleware` property: + + ```ts + // before + getMiddleware = (): Middleware => controller => next => async action => + next(action); + // after + middleware: Middleware = controller => next => async action => next(action); + ``` + +### Patch Changes + +- [#4407](https://github.com/reactive/data-client/pull/4407) [`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb) - Ship agent skills inside the packages + + Coding agents can now follow the skills for the version you have installed instead of guessing from older releases. Each package carries the skills it covers, and the new `data-client-skills` command (in `@data-client/react`, `vue`, `rest`, `graphql` and `endpoint`, so repos with only API definitions get it too) links them into `.agents/skills`, with `.claude/skills` linking to it, where Claude Code, Cursor and Codex load them as their own: + + ```bash + npx --no data-client-skills + ``` + + Commit the links. They point into `node_modules`, so they follow upgrades; run it again after adding, removing or upgrading `@data-client` packages to pick up new skills. [TanStack Intent](https://tanstack.com/intent) also finds these skills. + +- [#4209](https://github.com/reactive/data-client/pull/4209) [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169) Thanks [@renovate](https://github.com/apps/renovate)! - Support `@babel/runtime` 8 + + Apps on Babel 8 now share their `@babel/runtime` with Data Client instead of installing a second copy. Apps on Babel 7 keep working unchanged. + +- [#4103](https://github.com/reactive/data-client/pull/4103) [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69) - Fix `controller.set()` types for Array schemas + + `controller.set([Entity], rows)` and `controller.set(new schema.Array(Entity), rows)` now typecheck. This writes every row in one store update: each row merges with its stored entity, and entities not in `rows` stay. This works with `exactOptionalPropertyTypes` on too. + + Rows are typed by the Entity's fields. The schema holds one Entity, [Union](https://dataclient.io/rest/api/Union) (for mixed types) or [Invalidate](https://dataclient.io/rest/api/Invalidate) (to delete), in an Array or [Values](https://dataclient.io/rest/api/Values) (which takes an object keyed by id). + + Batch `set()` needs `@data-client/rest` (or `endpoint`/`graphql`) from this release, since older Entity classes don't type as `EntityInterface`. + + ```ts + // Before: TypeScript error on [Ticker], so batches became one set() per row + for (const row of rows) { + ctrl.set(Ticker, { product_id: row.product_id }, row); + } + + // After: one store update + ctrl.set([Ticker], rows); + + // Mixed Entity types, batch deletes, and rows keyed by id + const Message = new schema.Union({ ticker: Ticker, trade: Trade }, 'type'); + ctrl.set([Message], messages); + ctrl.set([new schema.Invalidate(Ticker)], [{ product_id: 'BTC-USD' }]); + ctrl.set(new schema.Values(Ticker), { 'BTC-USD': row }); + ``` + +- [#4230](https://github.com/reactive/data-client/pull/4230) [`46f1f24`](https://github.com/reactive/data-client/commit/46f1f24bcb04824805747ed2a1effe7baece337c) - Fix `controller.set()` types for a single [Invalidate](https://dataclient.io/rest/api/Invalidate) + + Deleting one entity with `set()` worked at runtime but failed to typecheck, since `Invalidate` isn't + [Queryable](https://dataclient.io/rest/api/schema#queryable). Pass the schema and the row to delete; the row is typed + by the Entity's fields. + + ```ts + // Before: TypeScript error, so a one-row batch was the workaround + ctrl.set([new Invalidate(Post)], [{ id: '5' }]); + + // After + ctrl.set(new Invalidate(Post), { id: '5' }); + ``` + + Like batch `set()`, it takes no `args` and no updater function. + +- [#4133](https://github.com/reactive/data-client/pull/4133) [`a82758c`](https://github.com/reactive/data-client/commit/a82758cd1998e58d7ad280407db28bd84f5d7b18) - Fix `controller.set()` accepting any value + + Values are now typed by the schema: Entities take their fields, while [Collection](https://dataclient.io/rest/api/Collection) + and [All](https://dataclient.io/rest/api/All) take a list of rows. [Query](https://dataclient.io/rest/api/Query) takes + the input of the schema it wraps, not what its `process()` returns. Updater functions must return the same. + + ```ts + // Before: these all typechecked, then failed or wrote nothing at runtime + ctrl.set(new schema.All(Todo), 42); + ctrl.set(TodoResource.getList.schema, 'anything'); + ctrl.set(Todo, { id: '5' }, { id: '5', completed: 'yes' }); + + // After: TypeScript errors on the above; these typecheck + ctrl.set(TodoResource.getList.schema, [{ id: '5', completed: true }]); + ctrl.set(new schema.All(Todo), [{ id: '5', completed: true }]); + ``` + + When each member declares its discriminator as a literal (like `readonly type = 'post'`), a + [Union](https://dataclient.io/rest/api/Union) row is checked against the member it selects. Only + declared fields are accepted, so a key read by a `schemaAttribute` function must be declared on each member. + + ```ts + const Feed = new schema.Union({ post: Post, comment: Comment }, 'type'); + // TypeScript error: commentBody is a Comment field, not a Post field + ctrl.set( + Feed, + { id: '1', type: 'post' }, + { type: 'post', commentBody: 'hi' }, + ); + ``` + +- [#4228](https://github.com/reactive/data-client/pull/4228) [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee) - Fix TypeScript error passing a `Controller` subclass to `DataProvider` or `DataClientPlugin` + + A plain `class MyController extends Controller` failed to typecheck as the `Controller` option of [DataProvider](https://dataclient.io/docs/api/DataProvider#Controller), Vue's [DataClientPlugin](https://dataclient.io/vue/api/DataClientPlugin#Controller), and the `@data-client/react/redux` `DataProvider`, so the documented example needed a cast. `MockController()` from `@data-client/core/mock` had the same error when wrapping your subclass. These now typecheck, and you can drop the casts. + + ```tsx + class MyController extends Controller { + doSomething = () => console.log('hi'); + } + + // Before: TypeScript error, so you had to cast + + app.use(DataClientPlugin, { Controller: MyController as typeof Controller }); + + // After + + app.use(DataClientPlugin, { Controller: MyController }); + ``` + +- [#4150](https://github.com/reactive/data-client/pull/4150) [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2) - Fix `useCache()` and `useDLE()` returning a truthy `Symbol` for deleted entities + + After an entity was deleted and its refetch failed, `useCache()` and `useDLE()` (React and Vue) returned an internal + `Symbol` instead of `undefined`. Since a `Symbol` is truthy, "not loaded" checks passed, and code went on to use it as + the entity: + + ```tsx + const todo = useCache(TodoResource.get, { id }); + if (!todo) return ; + // Before: reached here with a Symbol; todo.title was undefined and todo.title.trim() threw + // After: the placeholder renders + return ; + ``` + + [Controller.getResponse()](https://dataclient.io/docs/api/Controller#getResponse) and + [Controller.fetchIfStale()](https://dataclient.io/docs/api/Controller#fetchIfStale) now also give `undefined` there, + like [Controller.get()](https://dataclient.io/docs/api/Controller#get) already did. + +- [#4393](https://github.com/reactive/data-client/pull/4393) [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23) - Add recent actions to `globalThis.__DC_ACTIONS__` in development + + Coding agents and console debugging can now see what each store dispatched, including the fetches made while the + page loaded, without the Redux DevTools extension. [DevToolsManager](https://dataclient.io/docs/api/DevToolsManager#controllers) + keeps each store's recent actions in a `Map` keyed like `__DC_CONTROLLERS__`. Production builds don't include it. + + To keep memory small, only the newest 20 actions keep their payloads, and each polling key (endpoint and args) keeps + only its last two polls (`maxPollingActions`, default 4 actions). + + ```js title="Browser DevTools console" + __DC_ACTIONS__.get('Data Client: My App').slice(-10); + ``` + +- [#4163](https://github.com/reactive/data-client/pull/4163) [`159c963`](https://github.com/reactive/data-client/commit/159c9633679d95427fe4f626aec341c76e4578f8) - Fix slow updates in development while Redux DevTools is open + + With the [Redux DevTools](https://dataclient.io/docs/getting-started/debugging) extension open, every store update + stalled the page while DevTools serialized the store: about 20ms with 50 entities, and 200ms with 500. Apps doing + many `controller.set()` calls, polling, or live updates would stutter in development. Each update now serializes + 40-60x faster, and timestamps still show as readable times like `10:42:07.123 AM`. + +- [#4393](https://github.com/reactive/data-client/pull/4393) [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23) - Fix stores with the same devtools name hiding each other in `__DC_CONTROLLERS__` + + With two `DataProvider`s, or two Vue apps using `DataClientPlugin`, on one page and the default devtools name, the + second store replaced the first in `globalThis.__DC_CONTROLLERS__`, so debugging tools and coding agents could only find one. The second now + registers as `'Data Client: My App (2)'`, the next as `(3)`, and so on. + +- [#4227](https://github.com/reactive/data-client/pull/4227) [`47502c6`](https://github.com/reactive/data-client/commit/47502c664df913297fba3e5011a975dfd01c0d8d) - Type FETCH `action.meta.promise` as `Promise` + + Managers can now call `.finally()` and `.catch()` on a FETCH action's `meta.promise` without a TypeScript error. It was always a real `Promise` at runtime, but was typed `PromiseLike`, which only has `.then()`. + + ```ts + // Before: TypeScript error on .finally(), so both callbacks went to .then() + const track = () => + trackTiming(action.endpoint.name, performance.now() - start); + action.meta.promise.then(track, track); + + // After + action.meta.promise + .finally(() => { + trackTiming(action.endpoint.name, performance.now() - start); + }) + // the fetch's caller handles errors; this only observes timing + .catch(() => {}); + ``` + +- [#4250](https://github.com/reactive/data-client/pull/4250) [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a) - Fixture `args` accept readonly tuples + + Fixtures written with `args: [...] as const` now type-check when passed to [MockResolver](https://dataclient.io/docs/api/MockResolver), `renderDataHook()`, Vue's `renderDataCompose()` or `mockInitialState()`. Before, TypeScript rejected them with "The type 'readonly [...]' is 'readonly' and cannot be assigned to the mutable type", so you had to drop `as const` or cast. + + ```ts + const fixtures = [ + { + endpoint: TodoResource.getList, + args: [{ userId: 1 }] as const, + response: [{ id: 1, title: 'Write tests', userId: 1 }], + }, + ]; + + // Before: type error on `fixtures`. After: works as written + + + ; + ``` + +- [#4232](https://github.com/reactive/data-client/pull/4232) [`31b1820`](https://github.com/reactive/data-client/commit/31b182033106d5ce44352481577d3c321e39ebe9) - Fix `',' expected` errors on TypeScript 4.0 through 4.4 + + Importing `@data-client/react/redux`, `@data-client/react/nextjs` or `@data-client/test` failed to compile on TypeScript before 4.5, even with `skipLibCheck` on, because their declaration files used syntax those versions can't parse. They now compile on TypeScript 4.0 and later. + + ```ts + import { DataProvider } from '@data-client/react/nextjs'; + import { renderDataHook } from '@data-client/test'; + + // Before (TypeScript 4.0 to 4.4): + // node_modules/@data-client/react/lib/server/nextjs/DataProvider/DataProvider.d.ts(1,15): error TS1005: ',' expected. + // node_modules/@data-client/test/lib/makeRenderDataClient/index.d.ts(3,33): error TS1005: ',' expected. + // After: no errors + ``` + + `@data-client/vue/test` types now also resolve with `moduleResolution: "node"`. + +- [#4122](https://github.com/reactive/data-client/pull/4122) [`b4b502d`](https://github.com/reactive/data-client/commit/b4b502d545aab0cf75bf030f3de4607a2e3ab7dc) - Fix types for TypeScript 4.x when `skipLibCheck` is off + + TypeScript 4.0 through 4.7 no longer report `Cannot find name 'NoInfer'` from `@data-client/endpoint` or `@data-client/normalizr`, and TypeScript 4.0 through 4.9 no longer report `Only named exports may use 'export type'` from `@data-client/normalizr`. + + ```ts + import { Entity } from '@data-client/endpoint'; + import { normalize } from '@data-client/normalizr'; + + // Before (TypeScript 4.7, skipLibCheck: false): + // error TS2304: Cannot find name 'NoInfer'. + // error TS1383: Only named exports may use 'export type'. + // After: no errors + ``` + +- [#4378](https://github.com/reactive/data-client/pull/4378) [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53) - Clear error for a [Manager](https://dataclient.io/docs/api/Manager) without `middleware` + + A Manager must define [middleware](https://dataclient.io/docs/api/Manager#middleware). One without it used to crash + with `manager.middleware is not a function`; in development it now throws an error naming the Manager and linking to + the docs. + +- [#4019](https://github.com/reactive/data-client/pull/4019) [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e) Thanks [@renovate](https://github.com/apps/renovate)! - Fix TypeScript 7 module resolution for package exports + + TypeScript 7 requires a `types` condition in `package.json` `exports`. Without it, imports resolved to runtime entrypoints like `node.mjs` and lost declaration files. + +- [#4193](https://github.com/reactive/data-client/pull/4193) [`3e45adc`](https://github.com/reactive/data-client/commit/3e45adc831ead1923f0590d8b6ee316655610d69) - `createDataClient()` and `ProvidedDataClient` are deprecated + + They only exist to implement [DataClientPlugin](https://dataclient.io/vue/api/DataClientPlugin) and will stop being + exported in a future release. Nothing changes at runtime. If you call `createDataClient()` directly, install the + plugin instead and read the controller with [useController()](https://dataclient.io/vue/api/useController). + + ```ts title="main.ts" + import { DataClientPlugin } from '@data-client/vue'; + + app.use(DataClientPlugin, { managers, initialState }); + ``` + +- [#4148](https://github.com/reactive/data-client/pull/4148) [`c5e95d4`](https://github.com/reactive/data-client/commit/c5e95d46a8d68ef04ccbcdc7bf90f663357a8530) - `DataClientPlugin` garbage collects by default + + Previously, unused data was only removed from the store if you passed a `gcPolicy` yourself. It now defaults + to `new GCPolicy()`, matching `DataProvider` in `@data-client/react`, so you can drop the option unless you + customize it. + + Before + + ```ts + import { DataClientPlugin, GCPolicy } from '@data-client/vue'; + + app.use(DataClientPlugin, { gcPolicy: new GCPolicy() }); + ``` + + After + + ```ts + import { DataClientPlugin } from '@data-client/vue'; + + app.use(DataClientPlugin); + ``` + +- [#4221](https://github.com/reactive/data-client/pull/4221) [`76a50c8`](https://github.com/reactive/data-client/commit/76a50c853d863140122cecbeb141fb278853849d) - `waitForNextUpdate()` from `renderDataCompose()` is deprecated + + It gives up silently after 1 second, so a test could pass while the composable was still suspended. When the Promise + had already resolved, it waited the full second for nothing, and under `jest.useFakeTimers()` it could hang. Await the + result directly instead, and use `allSettled()` after changing props or calling the controller. + + `allSettled()` from `renderDataCompose()` and `mountDataClient()` now also waits for fetches that a prop change starts, + and for the component to re-render, so you no longer need `nextTick()` around it. It also waits on a `NetworkManager` + you pass in `managers`, instead of returning right away. + + #### Before + + ```ts + import { reactive } from 'vue'; + + const props = reactive({ id: 5 }); + const { result, waitForNextUpdate } = await renderDataCompose( + (props: { id: number }) => + useSuspense(ArticleResource.get, () => ({ id: props.id })), + { props, resolverFixtures }, + ); + await waitForNextUpdate(); + const article = await result; + + props.id = 6; + await waitForNextUpdate(); + ``` + + #### After + + ```ts + import { reactive } from 'vue'; + + const props = reactive({ id: 5 }); + const { result, allSettled } = await renderDataCompose( + (props: { id: number }) => + useSuspense(ArticleResource.get, () => ({ id: props.id })), + { props, resolverFixtures }, + ); + const article = await result; + + props.id = 6; + await allSettled(); + ``` + +- [#4142](https://github.com/reactive/data-client/pull/4142) [`f5cc51b`](https://github.com/reactive/data-client/commit/f5cc51b2f77230f64ab24d91eca0072521a24ded) - Fix `useDLE()` and `useCache()` dropping expired `invalidIfStale` data on unrelated store updates + + After an `invalidIfStale` response expired, any unrelated store update switched these composables to empty data, and + `useDLE()` stayed `loading` without starting a fetch. Expiry is now only re-checked when the response's expiry, the + arguments, or a reset changes, matching `@data-client/react`. + + The `vue` peer dependency is now `^3.4.0`. + + ```ts + const { data, loading } = useDLE(ArticleResource.get, { id: 5 }); + // ...after the response's dataExpiryLength passes + await ctrl.setResponse(UserResource.get, { id: 1 }, user); + // Before: loading.value === true, data.value === undefined, and no fetch starts + // After: loading.value === false, data.value is still the article + ``` + +- [#4143](https://github.com/reactive/data-client/pull/4143) [`743d8e3`](https://github.com/reactive/data-client/commit/743d8e3dcc5e69a0725616a3ffe2568dee5727e9) - Export `GCPolicy` from `@data-client/vue` + + ```ts + // Before + import { GCPolicy } from '@data-client/core'; + // After + import { GCPolicy } from '@data-client/vue'; + + app.use(DataClientPlugin, { + gcPolicy: new GCPolicy({ intervalMS: 60 * 1000 * 10 }), + }); + ``` + +- [#4115](https://github.com/reactive/data-client/pull/4115) [`e350950`](https://github.com/reactive/data-client/commit/e35095045ade70f8151202b357beef2a38ff8272) - Fix getter function arguments in Vue composables + + `useSuspense`, `useLive`, `useCache`, `useDLE`, `useFetch`, `useQuery` and `useSubscription` + were typed to accept getter functions as arguments, but only resolved refs at runtime. Getters + now work and are tracked reactively, just like refs and `computed`. + + ```ts + const props = defineProps<{ id: number }>(); + + // Before: getter was passed to the endpoint as-is + // After: re-fetches when props.id changes + const article = await useSuspense(ArticleResource.get, () => ({ + id: props.id, + })); + ``` + +- [#4270](https://github.com/reactive/data-client/pull/4270) [`1d693c6`](https://github.com/reactive/data-client/commit/1d693c6e26aa3774636844e5731c78ec9eabe86b) - Add `__INTERNAL__` export matching `@data-client/react`'s + + Tooling built on `@data-client/vue` can now use `createReducer`, `initialState` and friends without adding `@data-client/core` as a direct dependency. + +- [#4146](https://github.com/reactive/data-client/pull/4146) [`a8da8c7`](https://github.com/reactive/data-client/commit/a8da8c725de0097aff8fa9bab2f0db8ccfe7047c) - Fix `app.use(DataClientPlugin)` throwing `app.onUnmount is not a function` on Vue versions before 3.5 + + ```ts + const app = createApp(App); + // Before (Vue < 3.5): TypeError: app.onUnmount is not a function + // After: installs, and stops the DataClient when the app unmounts + app.use(DataClientPlugin); + ``` + +- [#4134](https://github.com/reactive/data-client/pull/4134) [`bd419cd`](https://github.com/reactive/data-client/commit/bd419cde7897f240440475adf942c64e6418307c) - Fix `useSuspense()`, `useDLE()` and `useFetch()` refetching stale data on every store update + + Once data was stale, any store update (such as `controller.set()`) made these composables refetch, so the server + response could overwrite the change. They now only refetch when the data's expiry, the arguments, or a reset changes, + matching `@data-client/react`. + + ```ts + const article = await useSuspense(ArticleResource.get, { id: 5 }); + // ...after the response's dataExpiryLength passes + await ctrl.set(Article, { id: 5 }, { id: 5, title: 'edited' }); + // Before: triggers a refetch that reverts title to the server value + // After: title stays 'edited' + ``` + +- [#4135](https://github.com/reactive/data-client/pull/4135) [`f03332e`](https://github.com/reactive/data-client/commit/f03332ea9a4e3b24dc1554cb3a4ff2ebc1b117ad) - Fix `useSuspense()` and `useLive()` fetch errors after arguments change being unhandled + + When ref or computed arguments changed and the new fetch failed, the error became an unhandled promise rejection + and the result became `undefined`. Reading the result now throws the error, like the first load does, so it reaches + `onErrorCaptured()`. + + ```ts + const props = defineProps<{ id: number }>(); + const todo = await useSuspense( + TodoResource.get, + computed(() => ({ id: props.id })), + ); + // Before: a failed fetch for a new id was an unhandled rejection; todo.value became undefined + // After: reading todo.value throws the fetch error, caught by onErrorCaptured() + ``` + +- [#4131](https://github.com/reactive/data-client/pull/4131) [`84b6766`](https://github.com/reactive/data-client/commit/84b67665f547bd52e7dc207af9ba768821041fac) - Fix `useSuspense()` and `useLive()` returning `undefined` while new arguments load + + When ref or computed arguments changed to data not yet in the store, the result became `undefined` until the + new fetch resolved, crashing templates like `{{ todo.title }}`. It now keeps the previous data until the new data arrives. + + ```ts + const props = defineProps<{ id: number }>(); + const todo = await useSuspense( + TodoResource.get, + computed(() => ({ id: props.id })), + ); + // Before: todo.value was undefined while the new id loaded + // After: todo.value keeps the previous todo until the new one arrives + ``` + +- [#4169](https://github.com/reactive/data-client/pull/4169) [`341e17c`](https://github.com/reactive/data-client/commit/341e17c087105b7cccd1609ad3df2cb15e10f1dc) - Fix Vue `useSuspense()` suspending on stale data instead of showing it while it refetches + + When a component mounted with cached data that was past its `dataExpiryLength` but still valid, `await useSuspense()` + waited for the refetch, so users saw the `` fallback instead of the data already on hand. Now, like React, + it renders the stale data right away and updates once the refetch resolves. Data that is missing, invalidated, or + [invalidIfStale](https://dataclient.io/rest/api/Endpoint#invalidifstale) still waits for the fetch. + +- [#4150](https://github.com/reactive/data-client/pull/4150) [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2) - Vue `useFetch()` keeps its response from being garbage collected while mounted, like React `useFetch()` and Vue `useSuspense()` + +- [#4114](https://github.com/reactive/data-client/pull/4114) [`7c24b70`](https://github.com/reactive/data-client/commit/7c24b706360208e167aff5d576ad679f7e8e2138) - Fix [useFetch()](https://dataclient.io/docs/api/useFetch) return type to be a read-only `Ref` + + `useFetch()` returns a read-only `Ref` holding the fetch promise, but was typed as returning the promise directly. + + ```ts + const promise = useFetch(PostResource.get, { id }); + // Before: promise.resolved typechecked, but was always undefined at runtime + // After: + if (!promise.value.resolved) { + // fetch is in-flight + } + ``` + +- Updated dependencies [[`b475613`](https://github.com/reactive/data-client/commit/b4756135b70e4fb79e9146114a1266b4f7b4a4cb), [`b4899d0`](https://github.com/reactive/data-client/commit/b4899d05731ad672cf17432ba603008a8c888169), [`f343f9d`](https://github.com/reactive/data-client/commit/f343f9d42a12f3ad763fac96362166d3b3156b69), [`46f1f24`](https://github.com/reactive/data-client/commit/46f1f24bcb04824805747ed2a1effe7baece337c), [`a82758c`](https://github.com/reactive/data-client/commit/a82758cd1998e58d7ad280407db28bd84f5d7b18), [`b55696c`](https://github.com/reactive/data-client/commit/b55696c72ad3e73e0a2f50d3751c7104cd4ad9ee), [`c3b8c54`](https://github.com/reactive/data-client/commit/c3b8c54bc3062cf082e67c215310cb98b3a03078), [`b1d40fd`](https://github.com/reactive/data-client/commit/b1d40fd80c9aa292f5cdbce9b573e7749d889069), [`74e67fa`](https://github.com/reactive/data-client/commit/74e67fa2c4f9f104f5b7a49e877a48e5963e4bd2), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`159c963`](https://github.com/reactive/data-client/commit/159c9633679d95427fe4f626aec341c76e4578f8), [`a32740d`](https://github.com/reactive/data-client/commit/a32740d14de86b7006ccc497484dd52c0bc54c23), [`4549122`](https://github.com/reactive/data-client/commit/4549122004244990a564781a61145ae9ea98370e), [`47502c6`](https://github.com/reactive/data-client/commit/47502c664df913297fba3e5011a975dfd01c0d8d), [`fc4b015`](https://github.com/reactive/data-client/commit/fc4b015ca0899a2685af881d17f765dce27ffc1a), [`31f3ddb`](https://github.com/reactive/data-client/commit/31f3ddbc178ade2a7f59f7029a54c416df70e003), [`5b1c7b8`](https://github.com/reactive/data-client/commit/5b1c7b8bd385f87e2d5e91a72dfa9b4d3eb4fd53), [`aa15f29`](https://github.com/reactive/data-client/commit/aa15f29f6b0a3b4ae655e2d114a419a3fc94ac7e)]: + - @data-client/core@0.19.0 + ## 0.18.1 ### Patch Changes diff --git a/packages/vue/package.json b/packages/vue/package.json index 074346495e20..4168ec38730b 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -1,6 +1,6 @@ { "name": "@data-client/vue", - "version": "0.18.1", + "version": "0.19.0", "description": "Async State Management without the Management. REST, GraphQL, SSE, Websockets, Fetch", "homepage": "https://dataclient.io", "repository": { diff --git a/yarn.lock b/yarn.lock index 81f36b560560..f1b4c57fb535 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5139,6 +5139,8 @@ __metadata: nock: "npm:13.3.1" rollup-plugins: "workspace:*" temporal-polyfill: "npm:^1.0.0" + bin: + data-client-skills: ./bin/data-client-skills.mjs languageName: unknown linkType: soft @@ -5153,10 +5155,12 @@ __metadata: "@types/node": "npm:^26.0.0" nock: "npm:13.3.1" rollup-plugins: "workspace:*" + bin: + data-client-skills: ./bin/data-client-skills.mjs languageName: unknown linkType: soft -"@data-client/img@npm:0.18.0, @data-client/img@workspace:*, @data-client/img@workspace:packages/img": +"@data-client/img@npm:0.19.0, @data-client/img@workspace:*, @data-client/img@workspace:packages/img": version: 0.0.0-use.local resolution: "@data-client/img@workspace:packages/img" dependencies: @@ -5174,7 +5178,7 @@ __metadata: react-dom: "npm:^19.2.1" rollup-plugins: "workspace:*" peerDependencies: - "@data-client/react": ^0.1.0 || ^0.2.0 || ^0.3.0 || ^0.4.0 || ^0.5.0 || ^0.7.0 || ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^0.14.0 || ^0.15.0 || ^0.16.0 || ^0.17.0 || ^0.18.0 + "@data-client/react": ^0.19.0 "@types/react": ^16.14.0 || ^17.0.0 || ^18.0.0-0 || ^19.0.0 react: ^16.14.0 || ^17.0.0 || ^18.0.0-0 || ^19.0.0 peerDependenciesMeta: @@ -5198,7 +5202,7 @@ __metadata: languageName: unknown linkType: soft -"@data-client/react@npm:0.18.1, @data-client/react@workspace:*, @data-client/react@workspace:packages/react": +"@data-client/react@npm:0.19.0, @data-client/react@workspace:*, @data-client/react@workspace:packages/react": version: 0.0.0-use.local resolution: "@data-client/react@workspace:packages/react" dependencies: @@ -5242,10 +5246,12 @@ __metadata: optional: true "@types/react": optional: true + bin: + data-client-skills: ./bin/data-client-skills.mjs languageName: unknown linkType: soft -"@data-client/rest@npm:0.18.1, @data-client/rest@workspace:*, @data-client/rest@workspace:packages/rest": +"@data-client/rest@npm:0.19.0, @data-client/rest@workspace:*, @data-client/rest@workspace:packages/rest": version: 0.0.0-use.local resolution: "@data-client/rest@workspace:packages/rest" dependencies: @@ -5259,6 +5265,8 @@ __metadata: nock: "npm:13.3.1" path-to-regexp: "npm:^8.1.0" rollup-plugins: "workspace:*" + bin: + data-client-skills: ./bin/data-client-skills.mjs languageName: unknown linkType: soft @@ -5285,7 +5293,7 @@ __metadata: rollup-plugins: "workspace:*" test-renderer: "npm:^1.3.0" peerDependencies: - "@data-client/react": ^0.12.15 || ^0.13.0 || ^0.14.0 || ^0.15.0 || ^0.16.0 || ^0.17.0 || ^0.18.0 + "@data-client/react": ^0.19.0 "@testing-library/react-hooks": ^8.0.0 "@testing-library/react-native": ^13.0.0 || ^14.0.0 "@types/react": ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-0 || ^19.0.0 @@ -5365,6 +5373,8 @@ __metadata: optional: true "@vue/test-utils": optional: true + bin: + data-client-skills: ./bin/data-client-skills.mjs languageName: unknown linkType: soft @@ -14760,9 +14770,9 @@ __metadata: "@anansi/webpack-config": "npm:22.0.1" "@babel/core": "npm:8.0.7" "@babel/runtime-corejs3": "npm:8.0.7" - "@data-client/img": "npm:0.18.0" - "@data-client/react": "npm:0.18.1" - "@data-client/rest": "npm:0.18.1" + "@data-client/img": "npm:0.19.0" + "@data-client/react": "npm:0.19.0" + "@data-client/rest": "npm:0.19.0" "@linaria/core": "npm:*" "@linaria/react": "npm:*" "@types/d3": "npm:^7"