From 1ca76593db62cc453c6928efc2e7c80ffa0d5067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Wed, 16 Sep 2026 18:51:41 -0300 Subject: [PATCH 1/9] chore(angular): prepare scoped npm prerelease publishing --- .changeset/angular-20-ssr-lazy-signals.md | 7 + .changeset/angular-devtools-theme.md | 5 + .changeset/angular-effect-subscriptions.md | 5 + .changeset/angular-restoration-factory.md | 10 + .changeset/angular-ssr-zone-timers.md | 5 + .changeset/angular-stable-release.md | 9 + .changeset/angular-store-zone-boundary.md | 5 + .changeset/config.json | 4 +- .changeset/persist-inject-factory.md | 5 + .changeset/pre.json | 35 + .changeset/reactive-devtools-options.md | 7 + .npmrc | 2 +- docs/config.json | 52 +- ...pclient-and-other-data-fetching-clients.md | 45 +- docs/framework/angular/devtools.md | 155 +- .../guides/background-fetching-indicators.md | 15 +- .../angular/guides/default-query-function.md | 15 +- .../angular/guides/dependent-queries.md | 8 +- .../angular/guides/disabling-queries.md | 2 +- .../guides/does-this-replace-client-state.md | 6 +- .../angular/guides/error-handling.md | 57 + .../angular/guides/important-defaults.md | 1 + .../angular/guides/infinite-queries.md | 2 +- .../guides/invalidations-from-mutations.md | 2 +- .../guides/migrating-from-experimental.md | 267 + .../guides/migrating-from-ngneat-query.md | 249 + .../guides/migrating-to-angular-query.md | 11 + docs/framework/angular/guides/mutations.md | 2 + .../angular/guides/parallel-queries.md | 11 +- docs/framework/angular/guides/queries.md | 10 +- .../angular/guides/query-cancellation.md | 2 +- .../angular/guides/query-invalidation.md | 2 +- .../framework/angular/guides/query-options.md | 4 +- .../framework/angular/guides/query-retries.md | 21 +- docs/framework/angular/guides/ssr.md | 107 + docs/framework/angular/guides/testing.md | 51 +- .../angular/guides/window-focus-refetching.md | 15 +- docs/framework/angular/installation.md | 29 +- docs/framework/angular/overview.md | 22 +- docs/framework/angular/quick-start.md | 37 +- .../functions/infiniteQueryOptions.md | 12 +- .../functions/injectInfiniteQuery.md | 257 +- .../reference/functions/injectIsFetching.md | 16 +- .../reference/functions/injectIsMutating.md | 16 +- .../reference/functions/injectIsRestoring.md | 16 +- .../reference/functions/injectMutation.md | 12 +- .../functions/injectMutationState.md | 18 +- .../reference/functions/injectQueries.md | 49 + .../reference/functions/injectQuery.md | 216 +- .../reference/functions/injectQueryClient.md | 36 - .../reference/functions/mutationOptions.md | 4 +- .../functions/provideAngularQuery.md | 36 - .../reference/functions/provideIsRestoring.md | 28 - .../reference/functions/provideQueryClient.md | 41 - .../functions/provideTanStackQuery.md | 107 +- .../reference/functions/queryFeature.md | 38 - .../reference/functions/queryOptions.md | 196 +- .../angular/reference/functions/toResource.md | 34 + .../reference/functions/withHydrationKey.md | 35 + .../functions/withNoQueryHydration.md | 16 + docs/framework/angular/reference/index.md | 158 +- .../interfaces/BaseInfiniteQueryNarrowing.md | 46 + .../interfaces/BaseMutationNarrowing.md | 49 +- .../interfaces/BaseQueryNarrowing.md | 39 +- .../interfaces/CreateBaseQueryOptions.md | 80 - .../interfaces/CreateInfiniteQueryOptions.md | 9 +- .../interfaces/CreateMutationOptions.md | 7 +- .../interfaces/CreateQueryOptions.md | 71 - .../DefinedInfiniteQueryNarrowing.md | 46 + .../interfaces/DefinedQueryNarrowing.md | 46 + .../interfaces/InjectInfiniteQueryOptions.md | 12 - .../interfaces/InjectIsFetchingOptions.md | 12 - .../interfaces/InjectIsMutatingOptions.md | 12 - .../interfaces/InjectMutationOptions.md | 12 - .../interfaces/InjectMutationStateOptions.md | 12 - .../interfaces/InjectQueriesOptions.md | 48 + .../interfaces/InjectQueryOptions.md | 12 - .../reference/interfaces/QueryFeature.md | 24 +- .../interfaces/QueryObserverOptions.md | 1 - .../reference/interfaces/QueryResource.md | 172 + .../type-aliases/CreateBaseMutationResult.md | 6 +- .../type-aliases/CreateBaseQueryResult.md | 13 +- .../type-aliases/CreateInfiniteQueryResult.md | 15 +- .../type-aliases/CreateMutateAsyncFunction.md | 5 +- .../type-aliases/CreateMutateFunction.md | 6 +- .../type-aliases/CreateMutationResult.md | 9 +- .../type-aliases/CreateQueryOptions.md | 28 + .../type-aliases/CreateQueryResult.md | 4 +- .../DefinedCreateInfiniteQueryResult.md | 10 +- .../type-aliases/DefinedCreateQueryResult.md | 10 +- .../DefinedInitialDataInfiniteOptions.md | 8 +- .../type-aliases/DefinedInitialDataOptions.md | 23 +- .../reference/type-aliases/DevtoolsFeature.md | 17 - .../type-aliases/MutationStateOptions.md | 50 + .../type-aliases/PersistQueryClientFeature.md | 13 - .../reference/type-aliases/QueriesOptions.md | 8 +- .../reference/type-aliases/QueriesResults.md | 7 +- .../reference/type-aliases/QueryFeatures.md | 21 - .../UndefinedInitialDataInfiniteOptions.md | 5 +- .../UndefinedInitialDataOptions.md | 5 +- .../UnusedSkipTokenInfiniteOptions.md | 6 +- .../type-aliases/UnusedSkipTokenOptions.md | 5 +- docs/framework/angular/resource-api.md | 160 + docs/framework/angular/typescript.md | 12 +- docs/framework/angular/zoneless.md | 12 - examples/angular/auto-refetching/angular.json | 3 + examples/angular/auto-refetching/package.json | 21 +- .../auto-refetching/src/app/app.config.ts | 20 +- .../components/auto-refetching.component.ts | 2 +- .../src/app/services/tasks.service.ts | 2 +- examples/angular/basic-persister/angular.json | 3 + examples/angular/basic-persister/package.json | 25 +- .../basic-persister/src/app/app.config.ts | 26 +- .../src/app/components/post.component.ts | 2 +- .../src/app/components/posts.component.ts | 2 +- examples/angular/basic/angular.json | 3 + examples/angular/basic/package.json | 21 +- examples/angular/basic/src/app/app.config.ts | 20 +- .../src/app/components/post.component.ts | 2 +- .../src/app/components/posts.component.ts | 2 +- examples/angular/devtools-panel/angular.json | 3 + examples/angular/devtools-panel/package.json | 23 +- .../devtools-panel/src/app/app.config.ts | 7 +- .../basic-devtools-panel-example.component.ts | 2 +- .../app/components/example-query.component.ts | 2 +- ...y-load-devtools-panel-example.component.ts | 11 +- .../.devcontainer/devcontainer.json | 4 + .../angular/dynamic-devtools/.eslintrc.cjs | 6 + examples/angular/dynamic-devtools/README.md | 10 + .../angular/dynamic-devtools/angular.json | 133 + .../angular/dynamic-devtools/package.json | 28 + .../dynamic-devtools/src/app/app.component.ts | 10 + .../dynamic-devtools/src/app/app.config.ts | 18 + .../dynamic-devtools-example.component.html | 18 + .../dynamic-devtools-example.component.ts | 29 + .../src/app/devtools-options.manager.ts | 19 + .../angular/dynamic-devtools/src/favicon.ico | Bin 0 -> 15086 bytes .../angular/dynamic-devtools/src/index.html | 13 + examples/angular/dynamic-devtools/src/main.ts | 5 + .../angular/dynamic-devtools/src/styles.css | 18 + .../dynamic-devtools/tsconfig.app.json | 9 + .../angular/dynamic-devtools/tsconfig.json | 31 + examples/angular/dynamic-queries/README.md | 10 + examples/angular/dynamic-queries/angular.json | 49 + examples/angular/dynamic-queries/package.json | 28 + .../dynamic-queries/src/app/app.component.ts | 107 + .../dynamic-queries/src/app/app.config.ts | 7 + .../angular/dynamic-queries/src/index.html | 12 + examples/angular/dynamic-queries/src/main.ts | 7 + .../angular/dynamic-queries/src/styles.css | 5 + .../angular/dynamic-queries/tsconfig.app.json | 6 + .../angular/dynamic-queries/tsconfig.json | 24 + .../angular.json | 3 + .../package.json | 21 +- .../src/app/app.config.ts | 20 +- .../src/app/components/example.component.ts | 2 +- .../angular/optimistic-updates/angular.json | 3 + .../angular/optimistic-updates/package.json | 23 +- .../optimistic-updates/src/app/app.config.ts | 20 +- .../optimistic-updates.component.ts | 2 +- .../src/app/services/tasks.service.ts | 2 +- examples/angular/pagination/angular.json | 3 + examples/angular/pagination/package.json | 21 +- .../angular/pagination/src/app/app.config.ts | 9 +- .../src/app/components/example.component.ts | 3 +- .../query-options-from-a-service/angular.json | 3 + .../query-options-from-a-service/package.json | 23 +- .../src/app/app.config.ts | 9 +- .../src/app/components/post.component.ts | 2 +- .../src/app/components/posts.component.ts | 2 +- .../src/app/services/queries-service.ts | 2 +- examples/angular/router/angular.json | 3 + examples/angular/router/package.json | 23 +- examples/angular/router/src/app/app.config.ts | 9 +- .../src/app/components/post.component.ts | 2 +- .../src/app/components/posts.component.ts | 2 +- examples/angular/rxjs/angular.json | 3 + examples/angular/rxjs/package.json | 23 +- examples/angular/rxjs/src/app/app.config.ts | 20 +- .../src/app/components/example.component.ts | 2 +- examples/angular/simple/angular.json | 3 + examples/angular/simple/package.json | 21 +- examples/angular/simple/src/app/app.config.ts | 9 +- .../components/simple-example.component.ts | 2 +- .../.devcontainer/devcontainer.json | 4 + examples/angular/ssr-persist/.eslintrc.cjs | 6 + examples/angular/ssr-persist/README.md | 14 + examples/angular/ssr-persist/angular.json | 140 + examples/angular/ssr-persist/package.json | 35 + .../ssr-persist/src/app/app.component.ts | 127 + .../ssr-persist/src/app/app.config.server.ts | 8 + .../angular/ssr-persist/src/app/app.config.ts | 31 + .../ssr-persist/src/app/app.routes.server.ts | 9 + .../client-persist-demo.component.ts | 84 + .../src/app/components/posts.component.ts | 70 + .../ssr-persist/src/app/query-client.ts | 21 + .../src/app/query-persist-scope.ts | 5 + .../src/app/services/posts.service.ts | 63 + examples/angular/ssr-persist/src/index.html | 12 + .../angular/ssr-persist/src/main.server.ts | 11 + examples/angular/ssr-persist/src/main.ts | 7 + examples/angular/ssr-persist/src/server.ts | 43 + examples/angular/ssr-persist/src/styles.css | 16 + .../angular/ssr-persist/tsconfig.app.json | 8 + examples/angular/ssr-persist/tsconfig.json | 29 + .../ssr/.devcontainer/devcontainer.json | 4 + examples/angular/ssr/.eslintrc.cjs | 6 + examples/angular/ssr/README.md | 6 + examples/angular/ssr/angular.json | 140 + examples/angular/ssr/package.json | 33 + examples/angular/ssr/src/app/app.component.ts | 57 + .../angular/ssr/src/app/app.config.server.ts | 8 + examples/angular/ssr/src/app/app.config.ts | 17 + .../angular/ssr/src/app/app.routes.server.ts | 9 + .../ssr/src/app/components/posts.component.ts | 70 + examples/angular/ssr/src/app/query-client.ts | 19 + .../ssr/src/app/services/posts.service.ts | 53 + examples/angular/ssr/src/index.html | 12 + examples/angular/ssr/src/main.server.ts | 11 + examples/angular/ssr/src/main.ts | 7 + examples/angular/ssr/src/server.ts | 43 + examples/angular/ssr/src/styles.css | 16 + examples/angular/ssr/tsconfig.app.json | 8 + examples/angular/ssr/tsconfig.json | 29 + .../to-resource-signal-forms/README.md | 21 + .../to-resource-signal-forms/angular.json | 58 + .../to-resource-signal-forms/package.json | 29 + .../src/app/app.component.css | 75 + .../src/app/app.component.ts | 249 + .../src/app/app.config.ts | 7 + .../src/app/validation-queries.service.ts | 89 + .../to-resource-signal-forms/src/index.html | 12 + .../to-resource-signal-forms/src/main.ts | 7 + .../to-resource-signal-forms/src/styles.css | 8 + .../tsconfig.app.json | 6 + .../to-resource-signal-forms/tsconfig.json | 24 + integrations/angular-cli-20/package.json | 25 +- .../angular-cli-20/src/app/app.config.ts | 8 +- integrations/angular-cli-20/src/app/app.ts | 2 +- packages/angular-query-devtools/README.md | 23 + packages/angular-query-devtools/package.json | 113 + .../scripts/prepack.js | 18 +- .../__tests__/inject-devtools-panel.test.ts | 76 +- .../src/__tests__/test-utils.ts | 19 + .../src/__tests__/with-devtools.test.ts | 345 +- .../src/devtools-panel/index.ts | 1 - .../devtools-panel/inject-devtools-panel.ts | 116 + .../src/devtools-panel/production/index.ts | 6 + .../src/devtools-panel/stub.ts | 12 +- .../src/devtools-panel/types.ts | 16 +- packages/angular-query-devtools/src/index.ts | 3 + .../src/production/index.ts | 2 + packages/angular-query-devtools/src/stub.ts | 9 + packages/angular-query-devtools/src/types.ts | 92 + .../src/with-devtools.ts | 172 + .../test-setup.ts | 1 + packages/angular-query-devtools/tsconfig.json | 23 + .../angular-query-devtools/tsconfig.prod.json | 9 + .../angular-query-devtools/tsconfig.spec.json | 15 + .../angular-query-devtools/vite.config.ts | 126 + .../angular-query-devtools/vitest.config.ts | 43 + .../angular-query-experimental/CHANGELOG.md | 499 -- .../angular-query-experimental/package.json | 112 - .../__tests__/inject-infinite-query.test-d.ts | 66 - .../__tests__/inject-infinite-query.test.ts | 227 - .../src/__tests__/inject-is-restoring.test.ts | 93 - .../src/__tests__/inject-queries.test-d.ts | 196 - .../src/__tests__/inject-queries.test.ts | 240 - .../src/__tests__/inject-query.test-d.ts | 357 -- .../src/__tests__/inject-query.test.ts | 700 --- .../__tests__/provide-query-client.test.ts | 38 - .../__tests__/provide-tanstack-query.test.ts | 38 - .../src/__tests__/signal-proxy.test.ts | 27 - .../src/__tests__/test-utils.ts | 77 - .../src/create-base-query.ts | 175 - .../devtools-panel/inject-devtools-panel.ts | 110 - .../src/devtools-panel/production/index.ts | 1 - .../src/devtools/index.ts | 8 - .../src/devtools/production/index.ts | 1 - .../src/devtools/stub.ts | 7 - .../src/devtools/types.ts | 116 - .../src/devtools/with-devtools.ts | 182 - .../src/inject-infinite-query.ts | 296 - .../src/inject-is-fetching.ts | 97 - .../src/inject-is-mutating.ts | 80 - .../src/inject-is-restoring.ts | 53 - .../src/inject-mutation-state.ts | 167 - .../src/inject-mutation.ts | 328 - .../src/inject-queries-experimental/index.ts | 1 - .../src/inject-queries.ts | 479 -- .../src/inject-query-client.ts | 22 - .../src/pending-tasks-compat.ts | 28 - .../src/providers.ts | 170 - .../src/signal-proxy.ts | 46 - .../angular-query-persist-client/README.md | 33 + .../angular-query-persist-client/package.json | 40 +- .../with-persist-query-client.test.ts | 527 +- .../src/with-persist-query-client.ts | 102 +- .../src/with-persist-query-client.types.ts | 15 + .../tsconfig.json | 2 +- .../vite.config.ts | 13 + .../.attw.json | 0 .../README.md | 48 +- .../eslint.config.js | 0 packages/angular-query/package.json | 109 + .../root.eslint.config.js | 0 .../schematics-build/ng-add.test.ts | 100 + .../angular-query/schematics/collection.json | 10 + .../angular-query/schematics/ng-add/index.ts | 143 + .../schematics/ng-add/schema.json | 17 + .../angular-query/schematics/ng-add/schema.ts | 3 + .../angular-query/schematics/package.json | 3 + .../scripts/inject-schematic-package-info.js | 47 + packages/angular-query/scripts/prepack.js | 116 + .../infinite-query-options.test-d.ts | 0 .../__tests__/infinite-query-options.test.ts | 0 .../__tests__/inject-infinite-query.test-d.ts | 176 + .../__tests__/inject-infinite-query.test.ts | 188 + .../src/__tests__/inject-is-fetching.test.ts | 63 +- .../src/__tests__/inject-is-mutating.test.ts | 51 +- .../src/__tests__/inject-is-restoring.test.ts | 51 + .../__tests__/inject-mutation-state.test-d.ts | 20 +- .../__tests__/inject-mutation-state.test.ts | 128 +- .../src/__tests__/inject-mutation.test-d.ts | 7 + .../src/__tests__/inject-mutation.test.ts | 731 +-- .../src/__tests__/inject-queries.test-d.ts | 307 + .../src/__tests__/inject-queries.test.ts | 1615 +++++ .../__tests__/inject-query-lifecycle.test.ts | 79 + .../src/__tests__/inject-query.test-d.ts | 250 + .../src/__tests__/inject-query.test.ts | 1636 +++++ .../src/__tests__/mutation-options.test-d.ts | 6 +- .../src/__tests__/mutation-options.test.ts | 73 +- .../src/__tests__/pending-tasks-ssr.test.ts | 128 + .../pending-tasks-ssr.zoneful.test.ts | 155 + .../src/__tests__/pending-tasks.test.ts | 436 +- .../provide-tanstack-query.test-d.ts | 44 + .../__tests__/provide-tanstack-query.test.ts | 79 + .../src/__tests__/query-options.test-d.ts | 26 +- .../src/__tests__/query-options.test.ts | 10 + .../src/__tests__/signal-proxy.test.ts | 77 + .../angular-query/src/__tests__/test-utils.ts | 78 + .../src/__tests__/upstream-issues.test.ts | 289 + .../src/__tests__/with-hydration.test.ts | 325 + .../src/__tests__/zoneful-integration.test.ts | 191 + .../angular-query/src/hydration-state-key.ts | 15 + .../src/index.ts | 32 +- .../src/infinite-query-options.ts | 7 +- .../angular-query/src/inject-base-query.ts | 107 + .../src/inject-infinite-query.ts | 200 + .../angular-query/src/inject-is-fetching.ts | 28 + .../angular-query/src/inject-is-mutating.ts | 28 + .../angular-query/src/inject-is-restoring.ts | 40 + .../src/inject-mutation-state.ts | 79 + packages/angular-query/src/inject-mutation.ts | 153 + packages/angular-query/src/inject-queries.ts | 201 + .../angular-query/src/inject-queries.types.ts | 223 + .../src/inject-query.ts | 78 +- packages/angular-query/src/internal.ts | 8 + .../src/mutation-options.ts | 4 +- packages/angular-query/src/providers.ts | 192 + .../src/query-options.ts | 33 +- packages/angular-query/src/query-resource.ts | 137 + .../src/types.ts | 277 +- .../__test__/inject-external-store.test.ts | 272 + .../src/utils/inject-external-store.ts | 88 + .../utils/inject-pending-tasks-lifecycle.ts | 41 + .../src/utils/inject-query-zone.ts | 7 + .../angular-query/src/utils/resource-types.ts | 10 + .../angular-query/src/utils/result-fields.ts | 73 + .../angular-query/src/utils/signal-proxy.ts | 29 + packages/angular-query/test-setup.ts | 9 + packages/angular-query/test-setup.zoneful.ts | 13 + .../tsconfig.json | 8 +- .../tsconfig.prod.json | 0 .../angular-query/tsconfig.schematics.json | 22 + packages/angular-query/tsconfig.spec.json | 15 + .../vite.config.ts | 51 +- packages/angular-query/vitest.config.ts | 57 + .../angular-query/vitest.schematics.config.ts | 11 + .../angular-query/vitest.zoneful.config.ts | 34 + pnpm-lock.yaml | 5469 +++++++++++------ pnpm-workspace.yaml | 2 + scripts/generate-docs.ts | 4 +- 383 files changed, 19429 insertions(+), 10274 deletions(-) create mode 100644 .changeset/angular-20-ssr-lazy-signals.md create mode 100644 .changeset/angular-devtools-theme.md create mode 100644 .changeset/angular-effect-subscriptions.md create mode 100644 .changeset/angular-restoration-factory.md create mode 100644 .changeset/angular-ssr-zone-timers.md create mode 100644 .changeset/angular-stable-release.md create mode 100644 .changeset/angular-store-zone-boundary.md create mode 100644 .changeset/persist-inject-factory.md create mode 100644 .changeset/pre.json create mode 100644 .changeset/reactive-devtools-options.md create mode 100644 docs/framework/angular/guides/error-handling.md create mode 100644 docs/framework/angular/guides/migrating-from-experimental.md create mode 100644 docs/framework/angular/guides/migrating-from-ngneat-query.md create mode 100644 docs/framework/angular/guides/migrating-to-angular-query.md create mode 100644 docs/framework/angular/guides/ssr.md create mode 100644 docs/framework/angular/reference/functions/injectQueries.md delete mode 100644 docs/framework/angular/reference/functions/injectQueryClient.md delete mode 100644 docs/framework/angular/reference/functions/provideAngularQuery.md delete mode 100644 docs/framework/angular/reference/functions/provideIsRestoring.md delete mode 100644 docs/framework/angular/reference/functions/provideQueryClient.md delete mode 100644 docs/framework/angular/reference/functions/queryFeature.md create mode 100644 docs/framework/angular/reference/functions/toResource.md create mode 100644 docs/framework/angular/reference/functions/withHydrationKey.md create mode 100644 docs/framework/angular/reference/functions/withNoQueryHydration.md create mode 100644 docs/framework/angular/reference/interfaces/BaseInfiniteQueryNarrowing.md delete mode 100644 docs/framework/angular/reference/interfaces/CreateBaseQueryOptions.md delete mode 100644 docs/framework/angular/reference/interfaces/CreateQueryOptions.md create mode 100644 docs/framework/angular/reference/interfaces/DefinedInfiniteQueryNarrowing.md create mode 100644 docs/framework/angular/reference/interfaces/DefinedQueryNarrowing.md delete mode 100644 docs/framework/angular/reference/interfaces/InjectInfiniteQueryOptions.md delete mode 100644 docs/framework/angular/reference/interfaces/InjectIsFetchingOptions.md delete mode 100644 docs/framework/angular/reference/interfaces/InjectIsMutatingOptions.md delete mode 100644 docs/framework/angular/reference/interfaces/InjectMutationOptions.md delete mode 100644 docs/framework/angular/reference/interfaces/InjectMutationStateOptions.md create mode 100644 docs/framework/angular/reference/interfaces/InjectQueriesOptions.md delete mode 100644 docs/framework/angular/reference/interfaces/InjectQueryOptions.md create mode 100644 docs/framework/angular/reference/interfaces/QueryResource.md create mode 100644 docs/framework/angular/reference/type-aliases/CreateQueryOptions.md delete mode 100644 docs/framework/angular/reference/type-aliases/DevtoolsFeature.md create mode 100644 docs/framework/angular/reference/type-aliases/MutationStateOptions.md delete mode 100644 docs/framework/angular/reference/type-aliases/PersistQueryClientFeature.md delete mode 100644 docs/framework/angular/reference/type-aliases/QueryFeatures.md create mode 100644 docs/framework/angular/resource-api.md delete mode 100644 docs/framework/angular/zoneless.md create mode 100644 examples/angular/dynamic-devtools/.devcontainer/devcontainer.json create mode 100644 examples/angular/dynamic-devtools/.eslintrc.cjs create mode 100644 examples/angular/dynamic-devtools/README.md create mode 100644 examples/angular/dynamic-devtools/angular.json create mode 100644 examples/angular/dynamic-devtools/package.json create mode 100644 examples/angular/dynamic-devtools/src/app/app.component.ts create mode 100644 examples/angular/dynamic-devtools/src/app/app.config.ts create mode 100644 examples/angular/dynamic-devtools/src/app/components/dynamic-devtools-example.component.html create mode 100644 examples/angular/dynamic-devtools/src/app/components/dynamic-devtools-example.component.ts create mode 100644 examples/angular/dynamic-devtools/src/app/devtools-options.manager.ts create mode 100644 examples/angular/dynamic-devtools/src/favicon.ico create mode 100644 examples/angular/dynamic-devtools/src/index.html create mode 100644 examples/angular/dynamic-devtools/src/main.ts create mode 100644 examples/angular/dynamic-devtools/src/styles.css create mode 100644 examples/angular/dynamic-devtools/tsconfig.app.json create mode 100644 examples/angular/dynamic-devtools/tsconfig.json create mode 100644 examples/angular/dynamic-queries/README.md create mode 100644 examples/angular/dynamic-queries/angular.json create mode 100644 examples/angular/dynamic-queries/package.json create mode 100644 examples/angular/dynamic-queries/src/app/app.component.ts create mode 100644 examples/angular/dynamic-queries/src/app/app.config.ts create mode 100644 examples/angular/dynamic-queries/src/index.html create mode 100644 examples/angular/dynamic-queries/src/main.ts create mode 100644 examples/angular/dynamic-queries/src/styles.css create mode 100644 examples/angular/dynamic-queries/tsconfig.app.json create mode 100644 examples/angular/dynamic-queries/tsconfig.json create mode 100644 examples/angular/ssr-persist/.devcontainer/devcontainer.json create mode 100644 examples/angular/ssr-persist/.eslintrc.cjs create mode 100644 examples/angular/ssr-persist/README.md create mode 100644 examples/angular/ssr-persist/angular.json create mode 100644 examples/angular/ssr-persist/package.json create mode 100644 examples/angular/ssr-persist/src/app/app.component.ts create mode 100644 examples/angular/ssr-persist/src/app/app.config.server.ts create mode 100644 examples/angular/ssr-persist/src/app/app.config.ts create mode 100644 examples/angular/ssr-persist/src/app/app.routes.server.ts create mode 100644 examples/angular/ssr-persist/src/app/components/client-persist-demo.component.ts create mode 100644 examples/angular/ssr-persist/src/app/components/posts.component.ts create mode 100644 examples/angular/ssr-persist/src/app/query-client.ts create mode 100644 examples/angular/ssr-persist/src/app/query-persist-scope.ts create mode 100644 examples/angular/ssr-persist/src/app/services/posts.service.ts create mode 100644 examples/angular/ssr-persist/src/index.html create mode 100644 examples/angular/ssr-persist/src/main.server.ts create mode 100644 examples/angular/ssr-persist/src/main.ts create mode 100644 examples/angular/ssr-persist/src/server.ts create mode 100644 examples/angular/ssr-persist/src/styles.css create mode 100644 examples/angular/ssr-persist/tsconfig.app.json create mode 100644 examples/angular/ssr-persist/tsconfig.json create mode 100644 examples/angular/ssr/.devcontainer/devcontainer.json create mode 100644 examples/angular/ssr/.eslintrc.cjs create mode 100644 examples/angular/ssr/README.md create mode 100644 examples/angular/ssr/angular.json create mode 100644 examples/angular/ssr/package.json create mode 100644 examples/angular/ssr/src/app/app.component.ts create mode 100644 examples/angular/ssr/src/app/app.config.server.ts create mode 100644 examples/angular/ssr/src/app/app.config.ts create mode 100644 examples/angular/ssr/src/app/app.routes.server.ts create mode 100644 examples/angular/ssr/src/app/components/posts.component.ts create mode 100644 examples/angular/ssr/src/app/query-client.ts create mode 100644 examples/angular/ssr/src/app/services/posts.service.ts create mode 100644 examples/angular/ssr/src/index.html create mode 100644 examples/angular/ssr/src/main.server.ts create mode 100644 examples/angular/ssr/src/main.ts create mode 100644 examples/angular/ssr/src/server.ts create mode 100644 examples/angular/ssr/src/styles.css create mode 100644 examples/angular/ssr/tsconfig.app.json create mode 100644 examples/angular/ssr/tsconfig.json create mode 100644 examples/angular/to-resource-signal-forms/README.md create mode 100644 examples/angular/to-resource-signal-forms/angular.json create mode 100644 examples/angular/to-resource-signal-forms/package.json create mode 100644 examples/angular/to-resource-signal-forms/src/app/app.component.css create mode 100644 examples/angular/to-resource-signal-forms/src/app/app.component.ts create mode 100644 examples/angular/to-resource-signal-forms/src/app/app.config.ts create mode 100644 examples/angular/to-resource-signal-forms/src/app/validation-queries.service.ts create mode 100644 examples/angular/to-resource-signal-forms/src/index.html create mode 100644 examples/angular/to-resource-signal-forms/src/main.ts create mode 100644 examples/angular/to-resource-signal-forms/src/styles.css create mode 100644 examples/angular/to-resource-signal-forms/tsconfig.app.json create mode 100644 examples/angular/to-resource-signal-forms/tsconfig.json create mode 100644 packages/angular-query-devtools/README.md create mode 100644 packages/angular-query-devtools/package.json rename packages/{angular-query-experimental => angular-query-devtools}/scripts/prepack.js (89%) rename packages/{angular-query-experimental => angular-query-devtools}/src/__tests__/inject-devtools-panel.test.ts (66%) create mode 100644 packages/angular-query-devtools/src/__tests__/test-utils.ts rename packages/{angular-query-experimental => angular-query-devtools}/src/__tests__/with-devtools.test.ts (68%) rename packages/{angular-query-experimental => angular-query-devtools}/src/devtools-panel/index.ts (84%) create mode 100644 packages/angular-query-devtools/src/devtools-panel/inject-devtools-panel.ts create mode 100644 packages/angular-query-devtools/src/devtools-panel/production/index.ts rename packages/{angular-query-experimental => angular-query-devtools}/src/devtools-panel/stub.ts (51%) rename packages/{angular-query-experimental => angular-query-devtools}/src/devtools-panel/types.ts (77%) create mode 100644 packages/angular-query-devtools/src/index.ts create mode 100644 packages/angular-query-devtools/src/production/index.ts create mode 100644 packages/angular-query-devtools/src/stub.ts create mode 100644 packages/angular-query-devtools/src/types.ts create mode 100644 packages/angular-query-devtools/src/with-devtools.ts rename packages/{angular-query-experimental => angular-query-devtools}/test-setup.ts (91%) create mode 100644 packages/angular-query-devtools/tsconfig.json create mode 100644 packages/angular-query-devtools/tsconfig.prod.json create mode 100644 packages/angular-query-devtools/tsconfig.spec.json create mode 100644 packages/angular-query-devtools/vite.config.ts create mode 100644 packages/angular-query-devtools/vitest.config.ts delete mode 100644 packages/angular-query-experimental/CHANGELOG.md delete mode 100644 packages/angular-query-experimental/package.json delete mode 100644 packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.ts delete mode 100644 packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts delete mode 100644 packages/angular-query-experimental/src/__tests__/inject-is-restoring.test.ts delete mode 100644 packages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts delete mode 100644 packages/angular-query-experimental/src/__tests__/inject-queries.test.ts delete mode 100644 packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts delete mode 100644 packages/angular-query-experimental/src/__tests__/inject-query.test.ts delete mode 100644 packages/angular-query-experimental/src/__tests__/provide-query-client.test.ts delete mode 100644 packages/angular-query-experimental/src/__tests__/provide-tanstack-query.test.ts delete mode 100644 packages/angular-query-experimental/src/__tests__/signal-proxy.test.ts delete mode 100644 packages/angular-query-experimental/src/__tests__/test-utils.ts delete mode 100644 packages/angular-query-experimental/src/create-base-query.ts delete mode 100644 packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts delete mode 100644 packages/angular-query-experimental/src/devtools-panel/production/index.ts delete mode 100644 packages/angular-query-experimental/src/devtools/index.ts delete mode 100644 packages/angular-query-experimental/src/devtools/production/index.ts delete mode 100644 packages/angular-query-experimental/src/devtools/stub.ts delete mode 100644 packages/angular-query-experimental/src/devtools/types.ts delete mode 100644 packages/angular-query-experimental/src/devtools/with-devtools.ts delete mode 100644 packages/angular-query-experimental/src/inject-infinite-query.ts delete mode 100644 packages/angular-query-experimental/src/inject-is-fetching.ts delete mode 100644 packages/angular-query-experimental/src/inject-is-mutating.ts delete mode 100644 packages/angular-query-experimental/src/inject-is-restoring.ts delete mode 100644 packages/angular-query-experimental/src/inject-mutation-state.ts delete mode 100644 packages/angular-query-experimental/src/inject-mutation.ts delete mode 100644 packages/angular-query-experimental/src/inject-queries-experimental/index.ts delete mode 100644 packages/angular-query-experimental/src/inject-queries.ts delete mode 100644 packages/angular-query-experimental/src/inject-query-client.ts delete mode 100644 packages/angular-query-experimental/src/pending-tasks-compat.ts delete mode 100644 packages/angular-query-experimental/src/providers.ts delete mode 100644 packages/angular-query-experimental/src/signal-proxy.ts create mode 100644 packages/angular-query-persist-client/README.md create mode 100644 packages/angular-query-persist-client/src/with-persist-query-client.types.ts rename packages/{angular-query-experimental => angular-query}/.attw.json (100%) rename packages/{angular-query-experimental => angular-query}/README.md (62%) rename packages/{angular-query-experimental => angular-query}/eslint.config.js (100%) create mode 100644 packages/angular-query/package.json rename packages/{angular-query-experimental => angular-query}/root.eslint.config.js (100%) create mode 100644 packages/angular-query/schematics-build/ng-add.test.ts create mode 100644 packages/angular-query/schematics/collection.json create mode 100644 packages/angular-query/schematics/ng-add/index.ts create mode 100644 packages/angular-query/schematics/ng-add/schema.json create mode 100644 packages/angular-query/schematics/ng-add/schema.ts create mode 100644 packages/angular-query/schematics/package.json create mode 100644 packages/angular-query/scripts/inject-schematic-package-info.js create mode 100644 packages/angular-query/scripts/prepack.js rename packages/{angular-query-experimental => angular-query}/src/__tests__/infinite-query-options.test-d.ts (100%) rename packages/{angular-query-experimental => angular-query}/src/__tests__/infinite-query-options.test.ts (100%) create mode 100644 packages/angular-query/src/__tests__/inject-infinite-query.test-d.ts create mode 100644 packages/angular-query/src/__tests__/inject-infinite-query.test.ts rename packages/{angular-query-experimental => angular-query}/src/__tests__/inject-is-fetching.test.ts (64%) rename packages/{angular-query-experimental => angular-query}/src/__tests__/inject-is-mutating.test.ts (67%) create mode 100644 packages/angular-query/src/__tests__/inject-is-restoring.test.ts rename packages/{angular-query-experimental => angular-query}/src/__tests__/inject-mutation-state.test-d.ts (54%) rename packages/{angular-query-experimental => angular-query}/src/__tests__/inject-mutation-state.test.ts (55%) rename packages/{angular-query-experimental => angular-query}/src/__tests__/inject-mutation.test-d.ts (95%) rename packages/{angular-query-experimental => angular-query}/src/__tests__/inject-mutation.test.ts (62%) create mode 100644 packages/angular-query/src/__tests__/inject-queries.test-d.ts create mode 100644 packages/angular-query/src/__tests__/inject-queries.test.ts create mode 100644 packages/angular-query/src/__tests__/inject-query-lifecycle.test.ts create mode 100644 packages/angular-query/src/__tests__/inject-query.test-d.ts create mode 100644 packages/angular-query/src/__tests__/inject-query.test.ts rename packages/{angular-query-experimental => angular-query}/src/__tests__/mutation-options.test-d.ts (98%) rename packages/{angular-query-experimental => angular-query}/src/__tests__/mutation-options.test.ts (84%) create mode 100644 packages/angular-query/src/__tests__/pending-tasks-ssr.test.ts create mode 100644 packages/angular-query/src/__tests__/pending-tasks-ssr.zoneful.test.ts rename packages/{angular-query-experimental => angular-query}/src/__tests__/pending-tasks.test.ts (62%) create mode 100644 packages/angular-query/src/__tests__/provide-tanstack-query.test-d.ts create mode 100644 packages/angular-query/src/__tests__/provide-tanstack-query.test.ts rename packages/{angular-query-experimental => angular-query}/src/__tests__/query-options.test-d.ts (100%) rename packages/{angular-query-experimental => angular-query}/src/__tests__/query-options.test.ts (58%) create mode 100644 packages/angular-query/src/__tests__/signal-proxy.test.ts create mode 100644 packages/angular-query/src/__tests__/test-utils.ts create mode 100644 packages/angular-query/src/__tests__/upstream-issues.test.ts create mode 100644 packages/angular-query/src/__tests__/with-hydration.test.ts create mode 100644 packages/angular-query/src/__tests__/zoneful-integration.test.ts create mode 100644 packages/angular-query/src/hydration-state-key.ts rename packages/{angular-query-experimental => angular-query}/src/index.ts (56%) rename packages/{angular-query-experimental => angular-query}/src/infinite-query-options.ts (99%) create mode 100644 packages/angular-query/src/inject-base-query.ts create mode 100644 packages/angular-query/src/inject-infinite-query.ts create mode 100644 packages/angular-query/src/inject-is-fetching.ts create mode 100644 packages/angular-query/src/inject-is-mutating.ts create mode 100644 packages/angular-query/src/inject-is-restoring.ts create mode 100644 packages/angular-query/src/inject-mutation-state.ts create mode 100644 packages/angular-query/src/inject-mutation.ts create mode 100644 packages/angular-query/src/inject-queries.ts create mode 100644 packages/angular-query/src/inject-queries.types.ts rename packages/{angular-query-experimental => angular-query}/src/inject-query.ts (75%) create mode 100644 packages/angular-query/src/internal.ts rename packages/{angular-query-experimental => angular-query}/src/mutation-options.ts (98%) create mode 100644 packages/angular-query/src/providers.ts rename packages/{angular-query-experimental => angular-query}/src/query-options.ts (89%) create mode 100644 packages/angular-query/src/query-resource.ts rename packages/{angular-query-experimental => angular-query}/src/types.ts (68%) create mode 100644 packages/angular-query/src/utils/__test__/inject-external-store.test.ts create mode 100644 packages/angular-query/src/utils/inject-external-store.ts create mode 100644 packages/angular-query/src/utils/inject-pending-tasks-lifecycle.ts create mode 100644 packages/angular-query/src/utils/inject-query-zone.ts create mode 100644 packages/angular-query/src/utils/resource-types.ts create mode 100644 packages/angular-query/src/utils/result-fields.ts create mode 100644 packages/angular-query/src/utils/signal-proxy.ts create mode 100644 packages/angular-query/test-setup.ts create mode 100644 packages/angular-query/test-setup.zoneful.ts rename packages/{angular-query-experimental => angular-query}/tsconfig.json (78%) rename packages/{angular-query-experimental => angular-query}/tsconfig.prod.json (100%) create mode 100644 packages/angular-query/tsconfig.schematics.json create mode 100644 packages/angular-query/tsconfig.spec.json rename packages/{angular-query-experimental => angular-query}/vite.config.ts (69%) create mode 100644 packages/angular-query/vitest.config.ts create mode 100644 packages/angular-query/vitest.schematics.config.ts create mode 100644 packages/angular-query/vitest.zoneful.config.ts diff --git a/.changeset/angular-20-ssr-lazy-signals.md b/.changeset/angular-20-ssr-lazy-signals.md new file mode 100644 index 00000000000..1b0c09dce13 --- /dev/null +++ b/.changeset/angular-20-ssr-lazy-signals.md @@ -0,0 +1,7 @@ +--- +'@tanstack/angular-query': minor +--- + +Angular 20 update, SSR support (hydration controls and TransferState), and lazy signal initialization for the Angular adapter. + +Reduce production bundle overhead with removable result-field enumeration, a tuple return from the internal base-query helper, and development guards around query and mutation injection-context assertions. diff --git a/.changeset/angular-devtools-theme.md b/.changeset/angular-devtools-theme.md new file mode 100644 index 00000000000..3a6a6d7072b --- /dev/null +++ b/.changeset/angular-devtools-theme.md @@ -0,0 +1,5 @@ +--- +'@tanstack/angular-query-devtools': patch +--- + +Restore the reactive `theme` option in Angular Query devtools. diff --git a/.changeset/angular-effect-subscriptions.md b/.changeset/angular-effect-subscriptions.md new file mode 100644 index 00000000000..a93bd569520 --- /dev/null +++ b/.changeset/angular-effect-subscriptions.md @@ -0,0 +1,5 @@ +--- +'@tanstack/angular-query': patch +--- + +Manage external-store subscriptions through Angular's lifecycle, keeping snapshot reads free of subscription side effects. Catch changes made during initialization and source replacement, preserve synchronous notifications once connected, and clean up on destruction. Public signatures are unchanged. diff --git a/.changeset/angular-restoration-factory.md b/.changeset/angular-restoration-factory.md new file mode 100644 index 00000000000..d5e5cd64859 --- /dev/null +++ b/.changeset/angular-restoration-factory.md @@ -0,0 +1,10 @@ +--- +'@tanstack/angular-query': major +'@tanstack/angular-query-persist-client': patch +--- + +Simplify `provideTanStackQuery` to accept only a DI factory. Replace `provideTanStackQuery(TOKEN)` with `provideTanStackQuery(() => inject(TOKEN))`. + +Move `provideIsRestoring` to the internal entry point used by the persistence integration. Applications configure persistence with `withPersistQueryClient`; restoration state is managed by that integration. + +Simplify persistence callback return types without changing behavior: synchronous results and returned promises remain supported, and promises are still awaited. diff --git a/.changeset/angular-ssr-zone-timers.md b/.changeset/angular-ssr-zone-timers.md new file mode 100644 index 00000000000..e92bad11e16 --- /dev/null +++ b/.changeset/angular-ssr-zone-timers.md @@ -0,0 +1,5 @@ +--- +'@tanstack/angular-query': patch +--- + +Prevent Zone.js server rendering from waiting for Query's background timers. Run adapter-owned Query operations outside Angular's zone while retaining PendingTasks tracking for fetches and mutations. Apply server retry and garbage-collection defaults per client without replacing global environment, notification, or timer configuration. diff --git a/.changeset/angular-stable-release.md b/.changeset/angular-stable-release.md new file mode 100644 index 00000000000..0f74358991b --- /dev/null +++ b/.changeset/angular-stable-release.md @@ -0,0 +1,9 @@ +--- +'@tanstack/angular-query': major +'@tanstack/angular-query-devtools': major +'@tanstack/angular-query-persist-client': major +--- + +Introduce the Angular packages at `5.0.0-rc.0`. Add the stable Angular Query adapter for Angular 20.1+, with effect-managed subscriptions, factory-based providers, SSR hydration controls, Resource interoperability, and an Angular CLI schematic. Add standalone Angular devtools and connect the persistence integration to the stable adapter. + +The experimental adapter remains available during migration. Existing persistence integration users must switch their adapter imports to `@tanstack/angular-query` and pass factories to `provideTanStackQuery` and `withPersistQueryClient`. diff --git a/.changeset/angular-store-zone-boundary.md b/.changeset/angular-store-zone-boundary.md new file mode 100644 index 00000000000..c579cfeed5e --- /dev/null +++ b/.changeset/angular-store-zone-boundary.md @@ -0,0 +1,5 @@ +--- +'@tanstack/angular-query': patch +--- + +Centralize external-store reads, subscriptions, and cleanup outside Angular's zone. Preserve separate boundaries for reactive option updates and imperative operations so Query background timers do not delay server rendering. diff --git a/.changeset/config.json b/.changeset/config.json index 984e1d89f1c..ff11f434eb5 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -6,11 +6,11 @@ ], "commit": false, "access": "public", - "baseBranch": "main", + "baseBranch": "angular-adapter-pre", "updateInternalDependencies": "patch", "fixed": [ [ - "@tanstack/angular-query-experimental", + "@tanstack/angular-query", "@tanstack/angular-query-persist-client", "@tanstack/eslint-plugin-query", "@tanstack/preact-query", diff --git a/.changeset/persist-inject-factory.md b/.changeset/persist-inject-factory.md new file mode 100644 index 00000000000..481a8f43d88 --- /dev/null +++ b/.changeset/persist-inject-factory.md @@ -0,0 +1,5 @@ +--- +'@tanstack/angular-query-persist-client': minor +--- + +Run the Angular persist factory in an injection context and drop the `deps` option, matching `withDevtools`. diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 00000000000..a63b0811ca7 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,35 @@ +{ + "mode": "pre", + "tag": "rc", + "initialVersions": { + "@tanstack/angular-query": "4.0.0", + "@tanstack/angular-query-devtools": "4.0.0", + "@tanstack/angular-query-experimental": "5.103.1", + "@tanstack/angular-query-persist-client": "4.0.0", + "@tanstack/eslint-plugin-query": "5.103.1", + "@tanstack/lit-query": "0.2.22", + "@tanstack/preact-query": "5.103.1", + "@tanstack/preact-query-devtools": "5.103.1", + "@tanstack/preact-query-persist-client": "5.103.1", + "@tanstack/query-async-storage-persister": "5.103.1", + "@tanstack/query-broadcast-client-experimental": "5.103.1", + "@tanstack/query-core": "5.103.1", + "@tanstack/query-devtools": "5.103.1", + "@tanstack/query-persist-client-core": "5.103.1", + "@tanstack/query-sync-storage-persister": "5.103.1", + "@tanstack/query-test-utils": "0.0.0", + "@tanstack/react-query": "5.103.1", + "@tanstack/react-query-devtools": "5.103.1", + "@tanstack/react-query-next-experimental": "5.103.1", + "@tanstack/react-query-persist-client": "5.103.1", + "@tanstack/solid-query": "5.103.1", + "@tanstack/solid-query-devtools": "5.103.1", + "@tanstack/solid-query-persist-client": "5.103.1", + "@tanstack/svelte-query": "6.2.1", + "@tanstack/svelte-query-devtools": "6.2.1", + "@tanstack/svelte-query-persist-client": "6.2.1", + "@tanstack/vue-query": "5.103.1", + "@tanstack/vue-query-devtools": "6.2.1" + }, + "changesets": [] +} diff --git a/.changeset/reactive-devtools-options.md b/.changeset/reactive-devtools-options.md new file mode 100644 index 00000000000..8bd406ef26c --- /dev/null +++ b/.changeset/reactive-devtools-options.md @@ -0,0 +1,7 @@ +--- +'@tanstack/angular-query-devtools': minor +--- + +Make mutable Angular devtools options individually signal-aware, construct the +devtools synchronously, and run reactive DOM updates in the after-render write +phase. diff --git a/.npmrc b/.npmrc index 268c392d3cb..a4be22c9207 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1 @@ -provenance=true +git-checks=false diff --git a/docs/config.json b/docs/config.json index 9bbeb14325c..918e29fb4bf 100644 --- a/docs/config.json +++ b/docs/config.json @@ -176,20 +176,20 @@ "to": "framework/angular/quick-start" }, { - "label": "Angular HttpClient and other data fetching clients", + "label": "Devtools", + "to": "framework/angular/devtools" + }, + { + "label": "Angular HttpClient", "to": "framework/angular/angular-httpclient-and-other-data-fetching-clients" }, { - "label": "Devtools", - "to": "framework/angular/devtools" + "label": "Resource API", + "to": "framework/angular/resource-api" }, { "label": "TypeScript", "to": "framework/angular/typescript" - }, - { - "label": "Zoneless", - "to": "framework/angular/zoneless" } ] }, @@ -774,6 +774,10 @@ "label": "Default Query Fn", "to": "framework/angular/guides/default-query-function" }, + { + "label": "SSR", + "to": "framework/angular/guides/ssr" + }, { "label": "Testing", "to": "framework/angular/guides/testing" @@ -781,6 +785,18 @@ { "label": "Does this replace state managers?", "to": "framework/angular/guides/does-this-replace-client-state" + }, + { + "label": "Migrating from Experimental", + "to": "framework/angular/guides/migrating-from-experimental" + }, + { + "label": "Migrating from ngneat/query", + "to": "framework/angular/guides/migrating-from-ngneat-query" + }, + { + "label": "Error Handling", + "to": "framework/angular/guides/error-handling" } ] }, @@ -5048,28 +5064,12 @@ "label": "Functions / partialMatchKey", "to": "framework/angular/reference/functions/partialMatchKey" }, - { - "label": "Functions / provideAngularQuery", - "to": "framework/angular/reference/functions/provideAngularQuery" - }, - { - "label": "Functions / provideIsRestoring", - "to": "framework/angular/reference/functions/provideIsRestoring" - }, - { - "label": "Functions / provideQueryClient", - "to": "framework/angular/reference/functions/provideQueryClient" - }, { "label": "Functions / provideTanStackQuery", "to": "framework/angular/reference/functions/provideTanStackQuery" }, { - "label": "Functions / queryFeature", - "to": "framework/angular/reference/functions/queryFeature" - }, - { - "label": "Functions / queryOptions", + "label": "queryOptions", "to": "framework/angular/reference/functions/queryOptions" }, { @@ -5132,10 +5132,6 @@ "label": "Interfaces / CancelOptions", "to": "framework/angular/reference/interfaces/CancelOptions" }, - { - "label": "Interfaces / CreateBaseQueryOptions", - "to": "framework/angular/reference/interfaces/CreateBaseQueryOptions" - }, { "label": "Interfaces / CreateInfiniteQueryOptions", "to": "framework/angular/reference/interfaces/CreateInfiniteQueryOptions" diff --git a/docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md b/docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md index 031e9fa8f8b..783a55990e5 100644 --- a/docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md +++ b/docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md @@ -1,22 +1,16 @@ --- id: Angular-HttpClient-and-other-data-fetching-clients -title: Angular HttpClient and other data fetching clients +title: Angular HttpClient --- -Because TanStack Query's fetching mechanisms are agnostically built on Promises, you can use literally any asynchronous data fetching client, including the browser native `fetch` API, `graphql-request`, and more. +TanStack Query works with any data fetching client that returns a Promise, including the browser's +`fetch` API and clients such as `graphql-request`. ## Using Angular's `HttpClient` for data fetching -`HttpClient` is a powerful and integrated part of Angular, which gives the following benefits: - -- Mock responses in unit tests using [provideHttpClientTesting](https://angular.dev/guide/http/testing). -- [Interceptors](https://angular.dev/guide/http/interceptors) can be used for a wide range of functionality including adding authentication headers, performing logging, etc. While some data fetching libraries have their own interceptor system, `HttpClient` interceptors are integrated with Angular's dependency injection system. -- `HttpClient` automatically informs [`PendingTasks`](https://angular.dev/api/core/PendingTasks#), which enables Angular to be aware of pending requests. Unit tests and SSR can use the resulting application _stableness_ information to wait for pending requests to finish. This makes unit testing much easier for [Zoneless](https://angular.dev/guide/zoneless) applications. -- When using SSR, `HttpClient` will [cache requests](https://angular.dev/guide/ssr#caching-data-when-using-HttpClient) performed on the server. This will prevent unneeded requests on the client. `HttpClient` SSR caching works out of the box. TanStack Query has its own hydration functionality which may be more powerful but requires some setup. Which one fits your needs best depends on your use case. - -### Using observables in `queryFn` - -As TanStack Query is a promise based library, observables from `HttpClient` need to be converted to promises. This can be done with the `lastValueFrom` or `firstValueFrom` functions from `rxjs`. +Angular's `HttpClient` returns Observables, which query and mutation functions do not consume +directly. Convert the Observable with RxJS's `firstValueFrom` or `lastValueFrom`. Query functions +can also return a synchronous value. ```ts @Component({ @@ -28,21 +22,28 @@ class ExampleComponent { readonly repoDataQuery = injectQuery(() => ({ queryKey: ['repoData'], queryFn: () => - lastValueFrom( + firstValueFrom( this.http.get('https://api.github.com/repos/tanstack/query'), ), })) } ``` -> Since Angular is moving towards RxJS as an optional dependency, it's expected that `HttpClient` will also support promises in the future. -> -> Support for observables in TanStack Query for Angular is planned. +For regular `HttpClient` requests, `firstValueFrom` resolves the single response and unsubscribes. +Use `lastValueFrom` when the Observable emits multiple values and the query should resolve with the +last one. + +Angular [HTTP interceptors](https://angular.dev/guide/http/interceptors) continue to apply to +requests made inside query and mutation functions. + +## SSR + +When using `HttpClient` with SSR, prefer Angular Query's built-in query hydration and disable +Angular's HTTP transfer cache. Otherwise, both systems serialize the same request data. -## Comparison table +Add +[`withNoHttpTransferCache()`](https://angular.dev/api/platform-browser/withNoHttpTransferCache) to +[`provideClientHydration()`](https://angular.dev/api/platform-browser/provideClientHydration). See +the [SSR guide](./guides/ssr.md) for the complete setup. -| Data fetching client | Pros | Cons | -| --------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------- | -| **Angular HttpClient** | Featureful and very well integrated with Angular. | Observables need to be converted to Promises. | -| **Fetch** | Browser native API, so adds nothing to bundle size. | Barebones API which lacks many features. | -| **Specialized libraries such as `graphql-request`** | Specialized features for specific use cases. | If it's not an Angular library it won't integrate well with the framework. | +For cancellation, see [Query Cancellation](./guides/query-cancellation.md). diff --git a/docs/framework/angular/devtools.md b/docs/framework/angular/devtools.md index 0103213a350..2af57274fef 100644 --- a/docs/framework/angular/devtools.md +++ b/docs/framework/angular/devtools.md @@ -11,79 +11,129 @@ title: Devtools ## Enable devtools +Add the devtools package (in addition to `@tanstack/angular-query`): + +```bash +npm install @tanstack/angular-query-devtools +``` + The devtools help you debug and inspect your queries and mutations. You can enable the devtools by adding `withDevtools` to `provideTanStackQuery`. -By default, Angular Query Devtools are only included in development mode bundles, so you don't need to worry about excluding them during a production build. +By default, Angular Query Devtools only load in development. ```ts -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { withDevtools } from '@tanstack/angular-query-devtools' export const appConfig: ApplicationConfig = { - providers: [provideTanStackQuery(new QueryClient(), withDevtools())], + providers: [provideTanStackQuery(() => new QueryClient(), withDevtools())], } ``` ## Devtools in production -Devtools are automatically excluded from production builds. However, it might be desirable to lazy load the devtools in production. - -To use `withDevtools` in production builds, import using the `production` sub-path. The function exported from the production subpath is identical to the main one, but won't be excluded from production builds. +If you need the real implementation in production, import from the `production` entrypoint. ```ts -import { withDevtools } from '@tanstack/angular-query-experimental/devtools/production' +import { withDevtools } from '@tanstack/angular-query-devtools/production' ``` -To control when devtools are loaded, you can use the `loadDevtools` option. +To control when devtools are rendered, use the `loadDevtools` option. -When not setting the option or setting it to 'auto', the devtools will be loaded automatically only when Angular runs in development mode. +When omitted or set to `'auto'`, devtools are only rendered in development mode. ```ts -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { withDevtools } from '@tanstack/angular-query-devtools' -provideTanStackQuery(new QueryClient(), withDevtools()) +providers: [provideTanStackQuery(() => new QueryClient(), withDevtools())] // which is equivalent to -provideTanStackQuery( - new QueryClient(), - withDevtools(() => ({ loadDevtools: 'auto' })), -) +providers: [ + provideTanStackQuery( + () => new QueryClient(), + withDevtools(() => ({ loadDevtools: 'auto' })), + ), +] ``` -When setting the option to true, the devtools will be loaded in both development and production mode. +When setting the option to true, the devtools will be rendered in both development and production mode. This is useful if you want to load devtools based on [Angular environment configurations](https://angular.dev/tools/cli/environments). E.g. you could set this to true when the application is running on your production build staging environment. ```ts import { environment } from './environments/environment' // Make sure to use the production sub-path to load devtools in production builds -import { withDevtools } from '@tanstack/angular-query-experimental/devtools/production' +import { withDevtools } from '@tanstack/angular-query-devtools/production' + +providers: [ + provideTanStackQuery( + () => new QueryClient(), + withDevtools(() => ({ loadDevtools: environment.loadDevtools })), + ), +] +``` + +When setting the option to false, the devtools will not be rendered. -provideTanStackQuery( - new QueryClient(), - withDevtools(() => ({ loadDevtools: environment.loadDevtools })), -) +```ts +providers: [ + provideTanStackQuery( + () => new QueryClient(), + withDevtools(() => ({ loadDevtools: false })), + ), +] ``` -When setting the option to false, the devtools will not be loaded. +### Webpack file replacements + +Some webpack-based Angular builders do not apply package export conditions when +they bundle application code. Use the explicit `production` and `stub` +entrypoints with Angular CLI file replacements to keep the devtools dependency +out of production bundles. + +Create an application-level import that can be replaced: ```ts -provideTanStackQuery( - new QueryClient(), - withDevtools(() => ({ loadDevtools: false })), -) +// src/app/query-devtools.ts +export { withDevtools } from '@tanstack/angular-query-devtools/production' ``` -## Derive options through reactivity +```ts +// src/app/query-devtools.stub.ts +export { withDevtools } from '@tanstack/angular-query-devtools/stub' +``` -Options are passed to `withDevtools` from a callback function to support reactivity through signals. In the following example -a signal is created from a RxJS observable that emits on a keyboard shortcut. When the derived signal is set to true, the devtools are lazily loaded. +Import the application-level module from your config: -The example below always loads devtools in development mode and loads on-demand in production mode when a keyboard shortcut is pressed. +```ts +import { withDevtools } from './query-devtools' +``` + +Then configure the production build: + +```json +{ + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "src/app/query-devtools.ts", + "with": "src/app/query-devtools.stub.ts" + } + ] + } + } +} +``` + +The same pattern is available for the programmatic panel: +`@tanstack/angular-query-devtools/devtools-panel/production` and +`@tanstack/angular-query-devtools/devtools-panel/stub`. + +## Reactive options + +Mutable options can be Angular signals. For example, a signal derived from a keyboard shortcut can show devtools on demand: ```ts import { Injectable, isDevMode } from '@angular/core' @@ -107,29 +157,23 @@ export class DevtoolsOptionsManager { } ``` -If you want to use an injectable such as a service in the callback you can use `deps`. The injected value will be passed as parameter to the callback function. - -This is similar to `deps` in Angular's [`useFactory`](https://angular.dev/guide/di/dependency-injection-providers#factory-providers-usefactory) provider. +The callback runs once in an Angular injection context, so it can call +`inject()`. Return signals as option values to update them reactively: ```ts // ... -// 👇 Note we import from the production sub-path to enable devtools lazy loading in production builds -import { withDevtools } from '@tanstack/angular-query-experimental/devtools/production' +// 👇 Import from the production sub-path to make devtools available in production builds +import { inject } from '@angular/core' +import { withDevtools } from '@tanstack/angular-query-devtools/production' export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(), provideTanStackQuery( - new QueryClient(), - withDevtools( - (devToolsOptionsManager: DevtoolsOptionsManager) => ({ - loadDevtools: devToolsOptionsManager.loadDevtools(), - }), - { - // `deps` is used to inject and pass `DevtoolsOptionsManager` to the `withDevtools` callback. - deps: [DevtoolsOptionsManager], - }, - ), + () => new QueryClient(), + withDevtools(() => ({ + loadDevtools: inject(DevtoolsOptionsManager).loadDevtools, + })), ), ], } @@ -137,11 +181,16 @@ export const appConfig: ApplicationConfig = { ### Options returned from the callback -Of these options `loadDevtools`, `client`, `position`, `errorTypes`, `buttonPosition`, `initialIsOpen`, and `theme` support reactivity through signals. +`loadDevtools`, `client`, `position`, `errorTypes`, `buttonPosition`, +`initialIsOpen`, and `theme` accept either their documented static value or a +signal containing that value. + +`styleNonce`, `shadowDOMTarget`, and `hideDisabledQueries` are construction-time +options and do not accept signals. - `loadDevtools?: 'auto' | boolean` - - Defaults to `auto`: lazily loads devtools when in development mode. Skips loading in production mode. - - Use this to control if the devtools are loaded. + - Omit or `'auto'`: load devtools only in development mode. + - Use this to control whether devtools load when using the `/production` import. - `initialIsOpen?: Boolean` - Set this to `true` if you want the tools to default to being open - `buttonPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right" | "relative"` @@ -164,4 +213,4 @@ Of these options `loadDevtools`, `client`, `position`, `errorTypes`, `buttonPosi - Set this to true to hide disabled queries from the devtools panel. - `theme?: "light" | "dark" | "system"` - Defaults to `system`. - - Set this to change the theme of the devtools panel. + - Sets the theme of the devtools panel. diff --git a/docs/framework/angular/guides/background-fetching-indicators.md b/docs/framework/angular/guides/background-fetching-indicators.md index 9e5c5804383..032ffae833b 100644 --- a/docs/framework/angular/guides/background-fetching-indicators.md +++ b/docs/framework/angular/guides/background-fetching-indicators.md @@ -6,7 +6,7 @@ replace: { 'useIsFetching': 'injectIsFetching', 'hook': 'function', - '@tanstack/react-query': '@tanstack/angular-query-experimental', + '@tanstack/react-query': '@tanstack/angular-query', } --- @@ -42,7 +42,7 @@ class TodosComponent { [//]: # 'Example2' ```angular-ts -import { injectIsFetching } from '@tanstack/angular-query-experimental' +import { injectIsFetching } from '@tanstack/angular-query' @Component({ selector: 'global-loading-indicator', @@ -58,3 +58,14 @@ export class GlobalLoadingIndicatorComponent { ``` [//]: # 'Example2' + +## Reactive filters + +Pass a factory when filtering activity. It can read signals or required component inputs: + +```ts +readonly isFetching = injectIsFetching(() => ({ queryKey: ['todos', this.userId()] })) +readonly isMutating = injectIsMutating(() => ({ mutationKey: ['save', this.userId()] })) +``` + +The count updates when these dependencies change. diff --git a/docs/framework/angular/guides/default-query-function.md b/docs/framework/angular/guides/default-query-function.md index a7ba445b318..9227eed2817 100644 --- a/docs/framework/angular/guides/default-query-function.md +++ b/docs/framework/angular/guides/default-query-function.md @@ -16,16 +16,17 @@ const defaultQueryFn: QueryFunction = async ({ queryKey }) => { } // provide the default query function to your app with defaultOptions -const queryClient = new QueryClient({ - defaultOptions: { - queries: { - queryFn: defaultQueryFn, +const createQueryClient = () => + new QueryClient({ + defaultOptions: { + queries: { + queryFn: defaultQueryFn, + }, }, - }, -}) + }) bootstrapApplication(MyAppComponent, { - providers: [provideTanStackQuery(queryClient)], + providers: [provideTanStackQuery(createQueryClient)], }) export class PostsComponent { diff --git a/docs/framework/angular/guides/dependent-queries.md b/docs/framework/angular/guides/dependent-queries.md index 38afbd491f7..a1a58286120 100644 --- a/docs/framework/angular/guides/dependent-queries.md +++ b/docs/framework/angular/guides/dependent-queries.md @@ -27,7 +27,13 @@ projectsQuery = injectQuery(() => ({ [//]: # 'Example2' ```ts -// injectQueries is under development for Angular Query +projectsQueries = injectQueries(() => ({ + queries: + this.userQuery.data()?.projectIds.map((projectId) => ({ + queryKey: ['project', projectId], + queryFn: () => getProjectById(projectId), + })) ?? [], +})) ``` [//]: # 'Example2' diff --git a/docs/framework/angular/guides/disabling-queries.md b/docs/framework/angular/guides/disabling-queries.md index b52266505aa..07bacf2d914 100644 --- a/docs/framework/angular/guides/disabling-queries.md +++ b/docs/framework/angular/guides/disabling-queries.md @@ -70,7 +70,7 @@ export class TodosComponent { [//]: # 'Example3' ```angular-ts -import { skipToken, injectQuery } from '@tanstack/angular-query-experimental' +import { skipToken, injectQuery } from '@tanstack/angular-query' @Component({ selector: 'todos', diff --git a/docs/framework/angular/guides/does-this-replace-client-state.md b/docs/framework/angular/guides/does-this-replace-client-state.md index 3872115c940..c1118ff4b28 100644 --- a/docs/framework/angular/guides/does-this-replace-client-state.md +++ b/docs/framework/angular/guides/does-this-replace-client-state.md @@ -4,8 +4,10 @@ title: Does TanStack Query replace global state managers? ref: docs/framework/react/guides/does-this-replace-client-state.md replace: { - 'useQuery': 'injectQuery', - 'useMutation': 'injectMutation', + 'Does TanStack Query replace Redux, MobX or other global state managers\?': 'Does TanStack Query replace global state managers?', + 'Redux, MobX, Zustand, etc.': 'NgRx Store, Signal Store, etc.', + '`useQuery`': '`injectQuery`', + '`useMutation`': '`injectMutation`', 'hook': 'function', } --- diff --git a/docs/framework/angular/guides/error-handling.md b/docs/framework/angular/guides/error-handling.md new file mode 100644 index 00000000000..4efdfcf87ef --- /dev/null +++ b/docs/framework/angular/guides/error-handling.md @@ -0,0 +1,57 @@ +--- +id: error-handling +title: Error Handling +--- + +Query and mutation errors are exposed through their result signals. The adapter does not report +failed requests to a global error handler automatically. + +To report cache failures to Angular's `ErrorHandler`, configure the cache callbacks when creating +the client. Capture the handler in the provider factory, where `inject()` is available: + +```ts +import { ErrorHandler, inject } from '@angular/core' +import { + MutationCache, + QueryCache, + QueryClient, + provideTanStackQuery, +} from '@tanstack/angular-query' + +export const queryProviders = provideTanStackQuery(() => { + const errors = inject(ErrorHandler) + + return new QueryClient({ + queryCache: new QueryCache({ + onError: (error, query) => { + if (query.meta?.reportToErrorHandler !== false) { + errors.handleError(error) + } + }, + }), + mutationCache: new MutationCache({ + onError: (error, _variables, _context, mutation) => { + if (mutation.meta?.reportToErrorHandler !== false) { + errors.handleError(error) + } + }, + }), + }) +}) +``` + +This example reports failures by default. Set `meta: { reportToErrorHandler: false }` on a query or +mutation which your application handles locally. Compose these callbacks with any cache callbacks +you already use. + +A query cache callback reports a failed cache operation once, even when several components observe +the query. Observer-only `select` errors and exceptions in options or `combine` computations are +not cache failures and are not reported by this recipe. + +`mutateAsync()` rejects and can be caught with `try`/`catch`. `mutate()` returns void; use mutation +callbacks or result signals for its error state. `refetch({ throwOnError: true })` opts into promise +rejection for that call. + +The [Resource view](../resource-api.md) throws from `value()` when its mapped status is `error`. +Check `hasValue()` before reading it. An uncaught error while Angular renders a template can still +reach Angular's error handler. This integration does not provide a component error boundary. diff --git a/docs/framework/angular/guides/important-defaults.md b/docs/framework/angular/guides/important-defaults.md index 886792038b1..95a6b1df98a 100644 --- a/docs/framework/angular/guides/important-defaults.md +++ b/docs/framework/angular/guides/important-defaults.md @@ -6,6 +6,7 @@ replace: { 'React': 'Angular', 'react-query': 'angular-query', + '@tanstack/angular-query': '@tanstack/angular-query', 'useQuery': 'injectQuery', 'useInfiniteQuery': 'injectInfiniteQuery', 'useMemo and useCallback': 'setting signal values', diff --git a/docs/framework/angular/guides/infinite-queries.md b/docs/framework/angular/guides/infinite-queries.md index f606cf8c6ba..202c4361377 100644 --- a/docs/framework/angular/guides/infinite-queries.md +++ b/docs/framework/angular/guides/infinite-queries.md @@ -10,7 +10,7 @@ replace: ```angular-ts import { Component, computed, inject } from '@angular/core' -import { injectInfiniteQuery } from '@tanstack/angular-query-experimental' +import { injectInfiniteQuery } from '@tanstack/angular-query' import { lastValueFrom } from 'rxjs' import { ProjectsService } from './projects-service' diff --git a/docs/framework/angular/guides/invalidations-from-mutations.md b/docs/framework/angular/guides/invalidations-from-mutations.md index e69c4e5be7c..a8e866224eb 100644 --- a/docs/framework/angular/guides/invalidations-from-mutations.md +++ b/docs/framework/angular/guides/invalidations-from-mutations.md @@ -20,7 +20,7 @@ postTodoMutation = injectMutation(() => ({ import { injectMutation, QueryClient, -} from '@tanstack/angular-query-experimental' +} from '@tanstack/angular-query' export class TodosComponent { readonly queryClient = inject(QueryClient) diff --git a/docs/framework/angular/guides/migrating-from-experimental.md b/docs/framework/angular/guides/migrating-from-experimental.md new file mode 100644 index 00000000000..b541fe0309f --- /dev/null +++ b/docs/framework/angular/guides/migrating-from-experimental.md @@ -0,0 +1,267 @@ +--- +id: migrating-from-experimental +title: Migrating from Angular Query Experimental +--- + +The stable package keeps the callback-based query, mutation, and signal result APIs from the +experimental adapter. Most application queries therefore only need an import change. The following +sections cover the breaking configuration and entrypoint changes. + +## Replace the experimental package + +```bash +npm uninstall @tanstack/angular-query-experimental +npm install @tanstack/angular-query +``` + +Angular 20.1 or newer is required by the stable package. + +```ts +import { injectQuery } from '@tanstack/angular-query-experimental' // [!code --] +import { injectQuery } from '@tanstack/angular-query' // [!code ++] +``` + +## Provide a client factory + +`provideTanStackQuery` no longer accepts a pre-created `QueryClient`. Pass a factory instead. + +```ts +provideTanStackQuery(new QueryClient()) // [!code --] +provideTanStackQuery(() => new QueryClient()) // [!code ++] +``` + +`provideTanStackQuery` now returns one `EnvironmentProviders` value rather than an array. Use it in +an environment injector, such as `ApplicationConfig.providers`, the `providers` passed to +`bootstrapApplication`, route-level `Route.providers`, or `createEnvironmentInjector`. It is not +supported in `@Component.providers` or `@Directive.providers`. Add the result directly; do not +spread it. + +```ts +providers: [...provideTanStackQuery(() => new QueryClient())] // [!code --] +providers: [provideTanStackQuery(() => new QueryClient())] // [!code ++] +``` + +## Remove deprecated provider and injection helpers + +`provideAngularQuery` and `injectQueryClient` have been removed. + +```ts +provideAngularQuery(new QueryClient()) // [!code --] +provideTanStackQuery(() => new QueryClient()) // [!code ++] +``` + +```ts +const queryClient = injectQueryClient() // [!code --] +const queryClient = inject(QueryClient) // [!code ++] +``` + +## Install the standalone devtools package + +Devtools no longer ship as entrypoints of the core Angular package. + +```bash +npm install @tanstack/angular-query-devtools +``` + +```ts +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' // [!code --] +import { withDevtools } from '@tanstack/angular-query-devtools' // [!code ++] +``` + +The production and panel entrypoints move in the same way: + +```ts +import { withDevtools } from '@tanstack/angular-query-experimental/devtools/production' // [!code --] +import { withDevtools } from '@tanstack/angular-query-devtools/production' // [!code ++] +``` + +The devtools options callback now runs in an injection context. Remove the `deps` option and call +`inject()` inside the callback instead. + +```ts +const optionsFromManager = (manager: DevtoolsOptionsManager) => ({ + loadDevtools: manager.loadDevtools, +}) + +withDevtools(optionsFromManager, { deps: [DevtoolsOptionsManager] }) // [!code --] +withDevtools(() => optionsFromManager(inject(DevtoolsOptionsManager))) // [!code ++] +``` + +See the [Devtools guide](../devtools.md) for setup, production entrypoints, and configuration +options. + +## Use the stable `injectQueries` export + +`injectQueries` is now exported from the main package. The helper must be called from an Angular +injection context. + +```ts +import { + injectQueries, // [!code --] +} from '@tanstack/angular-query-experimental/inject-queries-experimental' // [!code --] +import { injectQueries } from '@tanstack/angular-query' // [!code ++] + +const getQueries = () => ({ queries }) +const results = injectQueries(getQueries, injector) // [!code --] +const results = runInInjectionContext(injector, () => injectQueries(getQueries)) // [!code ++] +``` + +The `queries` callback is reactive, tuple inference is preserved, and `combine` can derive a single +result: + +```ts +readonly summary = injectQueries(() => ({ + queries: [todosOptions(), usersOptions()], + combine: ([todos, users]) => ({ + pending: todos.isPending || users.isPending, + todoCount: todos.data?.length ?? 0, + userCount: users.data?.length ?? 0, + }), +})) +``` + +## Review SSR hydration + +`provideTanStackQuery` now dehydrates the server cache into Angular `TransferState` and hydrates it +in the browser by default. In most SSR applications, no additional setup is necessary. + +If your application already performs manual dehydration and hydration, either remove the manual +implementation or disable the built-in behavior to avoid hydrating the same client twice: + +```ts +provideTanStackQuery(() => new QueryClient(), withNoQueryHydration()) +``` + +Give each client a unique key when multiple clients use automatic hydration: + +```ts +provideTanStackQuery( + () => new QueryClient(), + withHydrationKey('admin-query-cache'), +) +``` + +See the [SSR guide](./ssr.md) for request-scoped client setup and the interaction with Angular +`HttpClient` transfer caching. + +## Update tests that wait for stability + +Observed queries, parallel queries, and mutations started through the adapter register with Angular's `PendingTasks`. As a result, `ApplicationRef.whenStable()` and `fixture.whenStable()` wait until +that work settles. + +This can change existing tests that expected `whenStable()` to resolve while a request was still in +progress. Make sure mocked requests and mutations resolve or reject before awaiting stability. When +using fake timers, advance the timers and queued microtasks before awaiting `whenStable()`. Disabled +queries do not start fetching automatically; a manual refetch still registers pending work. + +See [Testing](./testing.md) for query, mutation, `HttpClientTestingController`, and fake-timer +examples. + +## New behavior that needs no migration + +The stable package also includes the following compatible improvements: + +- Query results can be converted into an Angular Resource with `toResource`. See the + [Resource API](../resource-api.md). +- `injectQueries` is supported from the main package with reactive options and field-level signals. +- Result field signals are evaluated lazily, so options can safely read required input signals without + being evaluated during class construction. +- Persistence options may be supplied as a browser-only factory, making references such as + `localStorage` safe in SSR applications. + +## Error handling + +Observer options no longer include `throwOnError`. Errors are exposed through the result's +`error`, `status`, and related signals, without an automatic global report. Cached query data +remains readable when a background refetch fails. + +```ts +injectQuery(() => ({ + queryKey: ['todos'], + queryFn: fetchTodos, + throwOnError: true, +})) // [!code --] +injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodos })) // [!code ++] +``` + +Remove observer `throwOnError` from query, infinite-query, and mutation options, including your +Angular-specific client defaults. The shared core client still accepts this option for other +framework adapters, but Angular does not use it for reporting. + +`mutateAsync()` still rejects on failure, and `mutate()` still returns void. Imperative options +such as `query.refetch({ throwOnError: true })` retain their promise-rejection behavior. +To report cache failures to Angular, use the [ErrorHandler guide](./error-handling.md). +`toResource(query).value()` throws when the Resource is in its error state; guard the read with +`hasValue()` or inspect `error()` first. + +## Use one client provider + +```ts +provideQueryClient(() => new QueryClient()) // [!code --] +provideTanStackQuery(() => new QueryClient()) // [!code ++] +``` + +`provideQueryClient` has been removed. Use `provideTanStackQuery`, which handles mounting, +unmounting, and default hydration. Replacing it with a bare Angular `useFactory` provider would +omit that setup. + +## Make activity filters reactive + +```ts +injectIsFetching({ queryKey: ['todos'] }) // [!code --] +injectIsFetching(() => ({ queryKey: ['todos', userId()] })) // [!code ++] + +injectIsMutating({ mutationKey: ['save'] }) // [!code --] +injectIsMutating(() => ({ mutationKey: ['save'] })) // [!code ++] +``` + +Calls without filters remain unchanged. Filter factories can read required inputs and signals; +changing a filter updates the count without waiting for a cache event. + +## Imperative methods + +Methods such as `refetch()` and `fetchNextPage()` use the current options even when called +immediately after changing an options signal. + +Read the current `injectQueries()` result when calling a method after adding, removing, or +reordering queries. + +`injectMutationState` selections and `injectQueries` combined results are no longer deeply +compared by the adapter. A newly allocated selected object or combined result can trigger consumers +even when its contents match the previous value. Prefer returning existing values when possible. + +## Stability and notifications + +Signal updates no longer enter `NgZone` or wait for adapter microtasks. Angular's change-detection +scheduler handles rendering. Keep reading reactive values as signals; callbacks do not gain an +injection context or guaranteed zone membership. + +Each mutation invocation blocks stability until its promise settles, including awaited lifecycle +callbacks. A later invocation completing, or calling `reset()`, does not release an earlier mutation's +work. Destroying the owning component or injector releases its pending tasks. Queries that are +paused offline continue to block stability until resumed, cancelled, or unobserved. + +## Persistence configuration + +Pass a factory to `withPersistQueryClient`: + +```ts +withPersistQueryClient(() => ({ + persistOptions: { persister }, +})) +``` + +The factory runs once per injector, in an injection context, only in the browser. +Create persisters that access `localStorage` inside this factory. + +## QueryClient factories + +`provideTanStackQuery` accepts a factory. If another provider already owns the client, +resolve it inside that factory: + +```ts +provideTanStackQuery(() => inject(MY_QUERY_CLIENT)) +``` + +Replace direct token arguments with this form. Persistence manages its restoration +state automatically through `withPersistQueryClient`. diff --git a/docs/framework/angular/guides/migrating-from-ngneat-query.md b/docs/framework/angular/guides/migrating-from-ngneat-query.md new file mode 100644 index 00000000000..e2d718671e6 --- /dev/null +++ b/docs/framework/angular/guides/migrating-from-ngneat-query.md @@ -0,0 +1,249 @@ +--- +id: migrating-from-ngneat-query +title: Migrating from ngneat/query +--- + +Angular Query requires Angular 20.1 or newer. + +This guide uses `@ngneat/query` in its examples. The same migration applies to its +`@openng/query` fork. + +## Replace the packages + +Remove whichever legacy package name your application uses, along with its devtools package. The +stable adapter includes `@tanstack/query-core` as a dependency, so remove a direct installation +unless your application imports it independently. + +```bash +npm uninstall @ngneat/query @ngneat/query-devtools @tanstack/query-core +npm install @tanstack/angular-query @tanstack/angular-query-devtools +``` + +If you use OpenNG, uninstall `@openng/query` and `@openng/query-devtools` instead. + +## Configure the `QueryClient` + +Replace `provideQueryClientOptions` with a `QueryClient` factory passed to +`provideTanStackQuery`. The factory runs in an Angular injection context, so it can call `inject()` +when building caches or default options. + +```ts +import { QueryCache } from '@ngneat/query' // [!code --] +import { provideQueryClientOptions } from '@ngneat/query' // [!code --] +import { QueryCache, QueryClient } from '@tanstack/angular-query' // [!code ++] +import { provideTanStackQuery } from '@tanstack/angular-query' // [!code ++] + +const queryClientConfig = { + queryCache: new QueryCache({ onError: handleError }), +} + +providers: [ + provideQueryClientOptions(queryClientConfig), // [!code --] + provideTanStackQuery(() => new QueryClient(queryClientConfig)), // [!code ++] +] +``` + +## Migrate queries + +The legacy `injectQuery()` call returned a function that accepted query options. The stable API +accepts a reactive options callback and returns the query result directly. + +```ts +private readonly useQuery = injectQuery() // [!code --] + +readonly todos = this.useQuery({ // [!code --] + queryKey: ['todos'], // [!code --] + queryFn: fetchTodos, // [!code --] +}) // [!code --] +readonly todos = injectQuery(() => ({ // [!code ++] + queryKey: ['todos'], // [!code ++] + queryFn: fetchTodos, // [!code ++] +})) // [!code ++] +``` + +Read signals inside the callback to update options reactively. This replaces calling +`updateOptions` yourself. + +```ts +readonly filter = signal('') +private readonly useQuery = injectQuery() // [!code --] +readonly todos = this.useQuery({ // [!code --] + queryKey: ['todos', this.filter()], // [!code --] + queryFn: () => fetchTodos(this.filter()), // [!code --] +}) // [!code --] +readonly todos = injectQuery(() => ({ // [!code ++] + queryKey: ['todos', this.filter()], // [!code ++] + queryFn: () => fetchTodos(this.filter()), // [!code ++] +})) // [!code ++] +``` + +When a helper must be called from a callback that is not already in an injection context, use +Angular's `runInInjectionContext` at the call site: + +```ts +runInInjectionContext(injector, () => injectQuery(() => queryOptions)) +``` + +## Migrate infinite queries and mutations + +`injectInfiniteQuery` and `injectMutation` use the same callback pattern: + +```ts +private readonly useInfiniteQuery = injectInfiniteQuery() // [!code --] +readonly posts = this.useInfiniteQuery({ // [!code --] + queryKey: ['posts'], // [!code --] + queryFn: ({ pageParam }) => fetchPosts(pageParam), // [!code --] + initialPageParam: 0, // [!code --] + getNextPageParam: (lastPage) => lastPage.nextId, // [!code --] +}) // [!code --] +readonly posts = injectInfiniteQuery(() => ({ // [!code ++] + queryKey: ['posts'], // [!code ++] + queryFn: ({ pageParam }) => fetchPosts(pageParam), // [!code ++] + initialPageParam: 0, // [!code ++] + getNextPageParam: (lastPage) => lastPage.nextId, // [!code ++] +})) // [!code ++] +``` + +```ts +private readonly useMutation = injectMutation() // [!code --] +readonly addTodo = this.useMutation({ // [!code --] + mutationFn: addTodo, // [!code --] +}) // [!code --] +readonly addTodo = injectMutation(() => ({ // [!code ++] + mutationFn: addTodo, // [!code ++] +})) // [!code ++] +``` + +Imperative methods remain direct methods, for example `addTodo.mutate(value)`, +`addTodo.reset()`, `posts.fetchNextPage()`, and `todos.refetch()`. + +## Migrate query and mutation results + +The legacy adapter exposed one signal and one Observable containing the entire observer result. +The stable adapter exposes each result field as a signal and keeps imperative methods as functions. + +```ts +todos.result().isPending // [!code --] +todos.result().data // [!code --] +todos.result().error // [!code --] +todos.isPending() // [!code ++] +todos.data() // [!code ++] +todos.error() // [!code ++] +``` + +Templates use the field signals in the same way: + +```angular-html +@if (todos.result().isPending) { +@if (todos.isPending()) { + Loading... +} @else if (todos.isError()) { + {{ todos.error()?.message }} +} @else { + @for (todo of todos.data(); track todo.id) { + {{ todo.title }} + } +} +``` + +There is no direct replacement for `result$`. Convert the field signal you need with Angular's +`toObservable`, or compose several fields with `computed` first. + +```ts +readonly todosResult$ = this.todos.result$ // [!code --] +readonly todosState = computed(() => ({ // [!code ++] + data: this.todos.data(), // [!code ++] + error: this.todos.error(), // [!code ++] + status: this.todos.status(), // [!code ++] +})) // [!code ++] +readonly todosResult$ = toObservable(this.todosState) // [!code ++] +``` + +Mutation state follows the same rule: + +```ts +addTodo.result().isPending // [!code --] +addTodo.result().data // [!code --] +addTodo.isPending() // [!code ++] +addTodo.data() // [!code ++] +``` + +## Convert Observable query functions + +The legacy adapter accepted an RxJS `Observable` from `queryFn` and `mutationFn`. The stable +adapter follows TanStack Query's Promise-based contract, so convert an Observable with +`firstValueFrom` or `lastValueFrom`. + +```ts +queryFn: () => this.http.get('/api/todos') // [!code --] +queryFn: () => lastValueFrom(this.http.get('/api/todos')) // [!code ++] +``` + +```ts +const createTodo = (todo: Todo) => this.http.post('/api/todos', todo) + +mutationFn: createTodo // [!code --] +mutationFn: (todo) => lastValueFrom(createTodo(todo)) // [!code ++] +``` + +See [Angular HttpClient](../angular-httpclient-and-other-data-fetching-clients.md) +for a complete example. If an Observable does not complete, prefer `firstValueFrom` or make it +complete before converting it. + +## Migrate background indicators + +`injectIsFetching` and `injectIsMutating` now accept a reactive filters callback and return a +`Signal`. + +```ts +private readonly useIsFetching = injectIsFetching() // [!code --] +readonly fetchingTodos = // [!code --] + this.useIsFetching({ queryKey: ['todos'] }).toSignal() // [!code --] +readonly fetchingTodos = injectIsFetching(() => ({ queryKey: ['todos'] })) // [!code ++] +``` + +```ts +private readonly useIsMutating = injectIsMutating() // [!code --] +readonly mutatingTodos = // [!code --] + this.useIsMutating({ mutationKey: ['todos'] }).toSignal() // [!code --] +readonly mutatingTodos = injectIsMutating(() => ({ mutationKey: ['todos'] })) // [!code ++] +``` + +Use `toObservable(this.fetchingTodos)` if a consumer still needs an Observable. + +## Inject the `QueryClient` + +Use Angular dependency injection directly instead of `injectQueryClient`: + +```ts +import { injectQueryClient } from '@ngneat/query' // [!code --] +import { inject } from '@angular/core' // [!code ++] +import { QueryClient } from '@tanstack/angular-query' // [!code ++] + +private readonly queryClient = injectQueryClient() // [!code --] +private readonly queryClient = inject(QueryClient) // [!code ++] +``` + +## Migrate devtools + +Replace the legacy devtools provider with the `withDevtools` feature from the standalone Angular +Query devtools package. + +```ts +import { provideQueryClientOptions } from '@ngneat/query' // [!code --] +import { provideQueryDevTools } from '@ngneat/query-devtools' // [!code --] +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' // [!code ++] +import { withDevtools } from '@tanstack/angular-query-devtools' // [!code ++] + +const devtools = withDevtools(() => ({ initialIsOpen: true })) + +providers: [ + provideQueryClientOptions({}), // [!code --] + provideQueryDevTools({ initialIsOpen: true }), // [!code --] + provideTanStackQuery(() => new QueryClient(), devtools), // [!code ++] +] +``` + +See the [Devtools guide](../devtools.md) for production entrypoints and reactive options. + +See [Error handling](./error-handling.md) for optional Angular `ErrorHandler` integration. diff --git a/docs/framework/angular/guides/migrating-to-angular-query.md b/docs/framework/angular/guides/migrating-to-angular-query.md new file mode 100644 index 00000000000..393d15ea7cc --- /dev/null +++ b/docs/framework/angular/guides/migrating-to-angular-query.md @@ -0,0 +1,11 @@ +--- +id: migrating-to-angular-query +title: Migrating to Angular Query +--- + +Choose the guide for your current adapter: + +- [Migrating from Angular Query Experimental](./migrating-from-experimental.md) +- [Migrating from ngneat/query or openng/query](./migrating-from-ngneat-query.md) + +Both target Angular 20.1 or newer. diff --git a/docs/framework/angular/guides/mutations.md b/docs/framework/angular/guides/mutations.md index b40933c55ba..18f3e53b4bc 100644 --- a/docs/framework/angular/guides/mutations.md +++ b/docs/framework/angular/guides/mutations.md @@ -272,3 +272,5 @@ queryClient.resumePausedMutations() [//]: # 'Example11' [//]: # 'Materials' [//]: # 'Materials' + +See [Error handling](./error-handling.md) to connect cache failures to Angular’s `ErrorHandler`. diff --git a/docs/framework/angular/guides/parallel-queries.md b/docs/framework/angular/guides/parallel-queries.md index 8e2e2348fc5..d6071e9d3b3 100644 --- a/docs/framework/angular/guides/parallel-queries.md +++ b/docs/framework/angular/guides/parallel-queries.md @@ -17,6 +17,9 @@ replace: [//]: # 'Example' ```ts +@Component({ + // ... +}) export class AppComponent { // The following queries will execute in parallel readonly usersQuery = injectQuery(() => ({ @@ -45,12 +48,14 @@ TanStack Query provides `injectQueries`, which you can use to dynamically execut [//]: # 'Example2' ```ts +@Component({ + // ... +}) export class AppComponent { users = signal>([]) - // Please note injectQueries is under development and this code does not work yet - readonly userQueries = injectQueries(() => ({ - queries: users().map((user) => { + userQueries = injectQueries(() => ({ + queries: this.users().map((user) => { return { queryKey: ['user', user.id], queryFn: () => fetchUserById(user.id), diff --git a/docs/framework/angular/guides/queries.md b/docs/framework/angular/guides/queries.md index 051d332bf8a..1bf5816d206 100644 --- a/docs/framework/angular/guides/queries.md +++ b/docs/framework/angular/guides/queries.md @@ -6,6 +6,7 @@ replace: { 'React': 'Angular', 'react-query': 'angular-query', + '@tanstack/angular-query': '@tanstack/angular-query', 'promise': 'promise or observable', 'custom hooks': 'services', 'the `useQuery` hook': '`injectQuery`', @@ -17,7 +18,7 @@ replace: [//]: # 'Example' ```ts -import { injectQuery } from '@tanstack/angular-query-experimental' +import { injectQuery } from '@tanstack/angular-query' export class TodosComponent { readonly todosQuery = injectQuery(() => ({ @@ -101,4 +102,11 @@ class TodosComponent {} [//]: # 'Example4' [//]: # 'Materials' + +Angular Query can convert each query result into a Resource-compatible view with `toResource`. See +the [Resource API](../resource-api.md) when an Angular API expects a +[Resource](https://angular.dev/api/core/Resource). + [//]: # 'Materials' + +See [Error handling](./error-handling.md) to connect cache failures to Angular’s `ErrorHandler`. diff --git a/docs/framework/angular/guides/query-cancellation.md b/docs/framework/angular/guides/query-cancellation.md index 6d107f2fffc..86de25536c3 100644 --- a/docs/framework/angular/guides/query-cancellation.md +++ b/docs/framework/angular/guides/query-cancellation.md @@ -15,7 +15,7 @@ However, if you consume the `AbortSignal`, the Promise will be cancelled (e.g. a ```ts import { HttpClient } from '@angular/common/http' -import { injectQuery } from '@tanstack/angular-query-experimental' +import { injectQuery } from '@tanstack/angular-query' postQuery = injectQuery(() => ({ enabled: this.postId() > 0, diff --git a/docs/framework/angular/guides/query-invalidation.md b/docs/framework/angular/guides/query-invalidation.md index 36956557dcf..eb287dd0070 100644 --- a/docs/framework/angular/guides/query-invalidation.md +++ b/docs/framework/angular/guides/query-invalidation.md @@ -8,7 +8,7 @@ replace: { 'useQuery': 'injectQuery', 'hooks': 'functions' } [//]: # 'Example2' ```ts -import { injectQuery, QueryClient } from '@tanstack/angular-query-experimental' +import { injectQuery, QueryClient } from '@tanstack/angular-query' class QueryInvalidationExample { readonly queryClient = inject(QueryClient) diff --git a/docs/framework/angular/guides/query-options.md b/docs/framework/angular/guides/query-options.md index 4ce9f836d59..19ed50384e8 100644 --- a/docs/framework/angular/guides/query-options.md +++ b/docs/framework/angular/guides/query-options.md @@ -7,7 +7,7 @@ ref: docs/framework/react/guides/query-options.md [//]: # 'Example1' ```ts -import { queryOptions, noop } from '@tanstack/angular-query-experimental' +import { noop, queryOptions } from '@tanstack/angular-query' @Injectable({ providedIn: 'root', @@ -38,7 +38,7 @@ queries = inject(QueriesService) postQuery = injectQuery(() => this.queries.post(this.postId())) -queryClient.query(this.queries.post(23)).catch(noop) +void queryClient.query(this.queries.post(23)).catch(noop) queryClient.setQueryData(this.queries.post(42).queryKey, newPost) ``` diff --git a/docs/framework/angular/guides/query-retries.md b/docs/framework/angular/guides/query-retries.md index a7b0b1841ca..e19c8f85a37 100644 --- a/docs/framework/angular/guides/query-retries.md +++ b/docs/framework/angular/guides/query-retries.md @@ -15,7 +15,7 @@ replace: [//]: # 'Example' ```ts -import { injectQuery } from '@tanstack/angular-query-experimental' +import { injectQuery } from '@tanstack/angular-query' // Make a specific query retry a certain number of times const todoQuery = injectQuery(() => ({ @@ -33,19 +33,20 @@ const todoQuery = injectQuery(() => ({ import { QueryCache, QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' + QueryClientProvider, +} from '@tanstack/angular-query' -const queryClient = new QueryClient({ - defaultOptions: { - queries: { - retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), +const createQueryClient = () => + new QueryClient({ + defaultOptions: { + queries: { + retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), + }, }, - }, -}) + }) bootstrapApplication(AppComponent, { - providers: [provideTanStackQuery(queryClient)], + providers: [provideTanStackQuery(createQueryClient)], }) ``` diff --git a/docs/framework/angular/guides/ssr.md b/docs/framework/angular/guides/ssr.md new file mode 100644 index 00000000000..a8a42e95294 --- /dev/null +++ b/docs/framework/angular/guides/ssr.md @@ -0,0 +1,107 @@ +--- +id: ssr +title: SSR +--- + +For [Angular SSR](https://angular.dev/guide/ssr), [`provideTanStackQuery`](../reference/functions/provideTanStackQuery.md) serializes the `QueryClient` cache into Angular's `TransferState` and restores it when the browser application starts. + +See the [Angular SSR example](https://github.com/TanStack/query/tree/main/examples/angular/ssr). The +[SSR persistence example](https://github.com/TanStack/query/tree/main/examples/angular/ssr-persist) +builds on the same setup with browser persistence. + +## Query client factory + +`provideTanStackQuery` registers the factory with Angular's `useFactory`. It runs once per root injector and in an injection context, so it can call `inject()`. Browser- and server-specific query defaults can stay inside this factory. + +Angular Query runs its query work outside `NgZone`, so background cache timers do not delay server rendering. Pending queries and mutations still participate in Angular's stability tracking. Server clients default to no retries and `gcTime: Infinity`; explicit client defaults are preserved. + +If you call `QueryClient` directly during rendering with a finite `gcTime`, run that work outside `NgZone` too. Await it or use Angular's `PendingTasks` when the HTML needs its result. + +```ts +import { isPlatformBrowser } from '@angular/common' +import { inject, PLATFORM_ID } from '@angular/core' +import { QueryClient } from '@tanstack/angular-query' + +export function createQueryClient() { + const isBrowser = isPlatformBrowser(inject(PLATFORM_ID)) + + return new QueryClient({ + defaultOptions: { + queries: { + // Keep hydrated data fresh briefly to avoid an immediate browser refetch. + staleTime: isBrowser ? 60_000 : 0, + }, + }, + }) +} +``` + +## Browser config + +Use the factory with `provideTanStackQuery` in your application config. Angular's HTTP transfer +cache is enabled by default with +[`provideClientHydration`](https://angular.dev/api/platform-browser/provideClientHydration). Add +[`withNoHttpTransferCache`](https://angular.dev/api/platform-browser/withNoHttpTransferCache) so +query results are not serialized once by each cache. + +```ts +import type { ApplicationConfig } from '@angular/core' +import { provideHttpClient } from '@angular/common/http' +import { + provideClientHydration, + withEventReplay, + withNoHttpTransferCache, +} from '@angular/platform-browser' +import { provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' +import { createQueryClient } from './query-client' + +export const appConfig: ApplicationConfig = { + providers: [ + provideHttpClient(), + provideClientHydration(withEventReplay(), withNoHttpTransferCache()), + provideTanStackQuery(createQueryClient, withDevtools()), + ], +} +``` + +## Server config + +Merge the application config with `provideServerRendering` in the server config. + +```ts +import { mergeApplicationConfig } from '@angular/core' +import { provideServerRendering, withRoutes } from '@angular/ssr' +import { appConfig } from './app.config' +import { serverRoutes } from './app.routes.server' + +export const serverConfig = mergeApplicationConfig(appConfig, { + providers: [provideServerRendering(withRoutes(serverRoutes))], +}) +``` + +## Multiple query clients + +Built-in hydration uses a default transfer key. For a second `QueryClient` in a child injector, pass a distinct key with `withHydrationKey` so each client's serialized cache stays separate. + +```ts +providers: [ + provideTanStackQuery( + createSecondaryQueryClient, + withHydrationKey('my-secondary-query-cache'), + ), +] +``` + +## Disabling built-in hydration + +If you need to opt out of TanStack Query's built-in `TransferState` integration for a specific injector, add `withNoQueryHydration()`. + +```ts +providers: [provideTanStackQuery(createQueryClient, withNoQueryHydration())] +``` + +## See also + +- [Angular HttpClient and data fetching](../angular-httpclient-and-other-data-fetching-clients.md) +- [Devtools](../devtools.md) diff --git a/docs/framework/angular/guides/testing.md b/docs/framework/angular/guides/testing.md index 7648d7f6b32..2bf32bfd2b1 100644 --- a/docs/framework/angular/guides/testing.md +++ b/docs/framework/angular/guides/testing.md @@ -9,11 +9,11 @@ TanStack Query's `inject*` functions integrate with [`PendingTasks`](https://ang This means tests and SSR can wait until mutations and queries resolve. In unit tests you can use `ApplicationRef.whenStable()` or `fixture.whenStable()` to await query completion. This works for both Zone.js and Zoneless setups. -> This integration requires Angular 19 or later. Earlier versions of Angular do not support `PendingTasks`. +> This adapter requires Angular 20.1 or later. It uses `PendingTasks` to keep application stability open while observed work is pending. ## TestBed setup -Create a fresh `QueryClient` for every spec and provide it with `provideTanStackQuery` or `provideQueryClient`. This keeps caches isolated and lets you change default options per test: +Create a fresh `QueryClient` for every spec and return it from the provider factory. Keeping a reference makes it easy to inspect or clear the cache: ```ts const queryClient = new QueryClient({ @@ -25,11 +25,11 @@ const queryClient = new QueryClient({ }) TestBed.configureTestingModule({ - providers: [provideTanStackQuery(queryClient)], + providers: [provideTanStackQuery(() => queryClient)], }) ``` -> If your applications actual TanStack Query config is used in unit tests, make sure `withDevtools` is not accidentally included in test providers. This can cause slow tests. It is best to keep test and production configs separate. +> If your application's TanStack Query config is used in unit tests, make sure `withDevtools` is not accidentally included in test providers. This can cause slow tests. It is best to keep test and production configs separate. If you share helpers, remember to call `queryClient.clear()` (or build a new instance) in `afterEach` so data from one test never bleeds into another. @@ -46,7 +46,7 @@ const query = TestBed.runInInjectionContext(() => })), ) -TestBed.tick() // Trigger effect +TestBed.tick() // Synchronize the test application // Application is stable when queries are idle await appRef.whenStable() @@ -69,6 +69,7 @@ For components, bootstrap them through `TestBed.createComponent`, then await `fi ```ts const fixture = TestBed.createComponent(ExampleComponent) +fixture.autoDetectChanges() await fixture.whenStable() expect(fixture.componentInstance.query.data()).toEqual({ value: 42 }) @@ -80,12 +81,17 @@ Retries slow failing tests because the default backoff runs three times. Set `re ## HttpClient & network stubs -Angular's `HttpClientTestingModule` plays nicely with PendingTasks. Register it alongside the Query provider and flush responses through `HttpTestingController`: +Angular's `provideHttpClientTesting` plays nicely with PendingTasks. Register it after +`provideHttpClient`, alongside the Query provider, and flush responses through +`HttpTestingController`: ```ts TestBed.configureTestingModule({ - imports: [HttpClientTestingModule], - providers: [provideTanStackQuery(queryClient)], + providers: [ + provideHttpClient(), + provideHttpClientTesting(), + provideTanStackQuery(() => queryClient), + ], }) const httpCtrl = TestBed.inject(HttpTestingController) @@ -96,6 +102,7 @@ const query = TestBed.runInInjectionContext(() => })), ) +TestBed.tick() // Synchronize the test application so the request starts const fixturePromise = TestBed.inject(ApplicationRef).whenStable() httpCtrl.expectOne('/api/todos').flush([{ id: 1 }]) await fixturePromise @@ -104,6 +111,17 @@ expect(query.data()).toEqual([{ id: 1 }]) httpCtrl.verify() ``` +Test observable results after normal Angular initialization and updates. For components, render +with `fixture.detectChanges()` and await `fixture.whenStable()` when the operation should finish. +For injection-context-only tests, synchronize the test application as shown above. When using +HTTP mocks or fake timers, flush the request or advance time before awaiting stability. + +Avoid asserting an exact subscription order or a stale intermediate value during initialization. +Those are implementation details. To test pending mutation or fetching state, hold the operation +open with a controlled promise and assert after rendering; do not await stability until you +resolve that promise. To test completed state, resolve the operation and await stability before +asserting the result. + ## Infinite queries & pagination Use the same pattern for infinite queries: call `fetchNextPage()`, advance timers if you are faking time, then await stability and assert on `data().pages`. @@ -112,19 +130,20 @@ Use the same pattern for infinite queries: call `fetchNextPage()`, advance timer const infinite = TestBed.runInInjectionContext(() => injectInfiniteQuery(() => ({ queryKey: ['pages'], - queryFn: ({ pageParam = 1 }) => fetchPage(pageParam), + initialPageParam: 1, + queryFn: ({ pageParam }) => fetchPage(pageParam), getNextPageParam: (last, all) => all.length + 1, })), ) +TestBed.tick() await appRef.whenStable() -expect(infinite.data().pages).toHaveLength(1) +expect(infinite.data()?.pages).toHaveLength(1) await infinite.fetchNextPage() -await vi.advanceTimersByTimeAsync(0) await appRef.whenStable() -expect(infinite.data().pages).toHaveLength(2) +expect(infinite.data()?.pages).toHaveLength(2) ``` ## Mutations and optimistic updates @@ -138,7 +157,7 @@ const mutation = TestBed.runInInjectionContext(() => mutation.mutate('test') -// Trigger effect +// Synchronize the test application TestBed.tick() await appRef.whenStable() @@ -147,11 +166,15 @@ expect(mutation.isSuccess()).toBe(true) expect(mutation.data()).toBe('TEST') ``` +`whenStable()` waits for every mutation invocation, including awaited lifecycle callbacks. +Resolve or reject all outstanding mocked mutations before awaiting stability; calling `reset()` +does not finish a request. Queries paused offline also keep stability open until resumed or cancelled. + ## Quick checklist - Fresh `QueryClient` per test (and clear it afterwards) - Disable or control retries to avoid timeouts - Advance timers + microtasks before `whenStable()` when using fake timers -- Use `HttpClientTestingModule` or your preferred mock to assert network calls +- Use `provideHttpClientTesting` or your preferred mock to assert network calls - Await `whenStable()` after every `refetch`, `fetchNextPage`, or mutation - Prefer `TestBed.runInInjectionContext` for service tests and `fixture.whenStable()` for component tests diff --git a/docs/framework/angular/guides/window-focus-refetching.md b/docs/framework/angular/guides/window-focus-refetching.md index 14490ba07ca..36e446238df 100644 --- a/docs/framework/angular/guides/window-focus-refetching.md +++ b/docs/framework/angular/guides/window-focus-refetching.md @@ -2,7 +2,7 @@ id: window-focus-refetching title: Window Focus Refetching ref: docs/framework/react/guides/window-focus-refetching.md -replace: { '@tanstack/react-query': '@tanstack/angular-query-experimental' } +replace: { '@tanstack/react-query': '@tanstack/angular-query' } --- [//]: # 'Example' @@ -11,13 +11,14 @@ replace: { '@tanstack/react-query': '@tanstack/angular-query-experimental' } export const appConfig: ApplicationConfig = { providers: [ provideTanStackQuery( - new QueryClient({ - defaultOptions: { - queries: { - refetchOnWindowFocus: false, // default: true + () => + new QueryClient({ + defaultOptions: { + queries: { + refetchOnWindowFocus: false, // default: true + }, }, - }, - }), + }), ), ], } diff --git a/docs/framework/angular/installation.md b/docs/framework/angular/installation.md index dffc092e7cd..5cfae0bd3bd 100644 --- a/docs/framework/angular/installation.md +++ b/docs/framework/angular/installation.md @@ -3,32 +3,45 @@ id: installation title: Installation --- -> IMPORTANT: This library is currently in an experimental stage. This means that breaking changes will happen in minor AND patch releases. Upgrade carefully. If you use this in production while in experimental stage, please lock your version to a patch-level version to avoid unexpected breaking changes. +_Angular Query is compatible with Angular v20.1 and higher._ -### NPM +### Angular CLI -_Angular Query is compatible with Angular v16 and higher_ +```bash +ng add @tanstack/angular-query +``` + +This installs the package and devtools, then configures an SSR-safe `QueryClient` factory with +`withDevtools()`. + +### Package managers ```bash -npm i @tanstack/angular-query-experimental +npm i @tanstack/angular-query ``` or ```bash -pnpm add @tanstack/angular-query-experimental +pnpm add @tanstack/angular-query ``` or ```bash -yarn add @tanstack/angular-query-experimental +yarn add @tanstack/angular-query ``` or ```bash -bun add @tanstack/angular-query-experimental +bun add @tanstack/angular-query +``` + +If you want Angular Query devtools, install the standalone devtools package as well: + +```bash +npm i @tanstack/angular-query-devtools ``` -> Wanna give it a spin before you download? Try out the [simple](./examples/simple) or [basic](./examples/basic) examples! +> Want to try it first? See the [simple](./examples/simple) or [basic](./examples/basic) example. diff --git a/docs/framework/angular/overview.md b/docs/framework/angular/overview.md index 31dd1131ccb..83dd7497cf5 100644 --- a/docs/framework/angular/overview.md +++ b/docs/framework/angular/overview.md @@ -3,17 +3,13 @@ id: overview title: Overview --- -> IMPORTANT: This library is currently in an experimental stage. This means that breaking changes will happen in minor AND patch releases. Upgrade carefully. If you use this in production while in experimental stage, please lock your version to a patch-level version to avoid unexpected breaking changes. +The `@tanstack/angular-query` package offers a 1st-class API for using TanStack Query via Angular. -The `@tanstack/angular-query-experimental` package offers a 1st-class API for using TanStack Query via Angular. - -## Feedback welcome! - -We are in the process of getting to a stable API for TanStack Query on Angular. If you have any feedback, please contact us at the [TanStack Discord](https://tlinz.com/discord) server or [visit this discussion](https://github.com/TanStack/query/discussions/6293) on Github. +If you have any feedback, please contact us at the [TanStack Discord](https://tlinz.com/discord) server or [visit this discussion](https://github.com/TanStack/query/discussions/6293) on Github. ## Supported Angular Versions -TanStack Query is compatible with Angular v16 and higher. +TanStack Query is compatible with Angular v20.1 and higher. TanStack Query (FKA React Query) is often described as the missing data-fetching library for web applications, but in more technical terms, it makes **fetching, caching, synchronizing and updating server state** in your web applications a breeze. @@ -63,8 +59,7 @@ In the example below, you can see TanStack Query in its most basic and simple fo ```angular-ts import { ChangeDetectionStrategy, Component, inject } from '@angular/core' import { HttpClient } from '@angular/common/http' -import { CommonModule } from '@angular/common' -import { injectQuery } from '@tanstack/angular-query-experimental' +import { injectQuery } from '@tanstack/angular-query' import { lastValueFrom } from 'rxjs' @Component({ @@ -73,11 +68,10 @@ import { lastValueFrom } from 'rxjs' template: ` @if (repoDataQuery.isPending()) { Loading... - } - @if (repoDataQuery.error()) { - An error has occurred: {{ repoDataQuery.error().message }} - } - @if (repoDataQuery.data(); as data) { + } @else if (query.isError()) { + An error has occurred: {{ query.error().message }} + } @else if (query.isSuccess()) { + @let data = query.data();

{{ data.name }}

{{ data.description }}

👀 {{ data.subscribers_count }} diff --git a/docs/framework/angular/quick-start.md b/docs/framework/angular/quick-start.md index cfe29d87b58..c7358a767af 100644 --- a/docs/framework/angular/quick-start.md +++ b/docs/framework/angular/quick-start.md @@ -3,42 +3,25 @@ id: quick-start title: Quick Start --- -> IMPORTANT: This library is currently in an experimental stage. This means that breaking changes will happen in minor AND patch releases. Upgrade carefully. If you use this in production while in experimental stage, please lock your version to a patch-level version to avoid unexpected breaking changes. - [//]: # 'Example' If you're looking for a fully functioning example, please have a look at our [basic codesandbox example](./examples/basic) -### Provide the client to your App +### Configure the QueryClient -```ts -import { provideHttpClient } from '@angular/common/http' -import { - provideTanStackQuery, - QueryClient, -} from '@tanstack/angular-query-experimental' - -bootstrapApplication(AppComponent, { - providers: [provideHttpClient(), provideTanStackQuery(new QueryClient())], -}) -``` - -or in a NgModule-based app +Pass a factory to `provideTanStackQuery`. Angular runs it once per injector and in an injection context, so it can use `inject()`. ```ts import { provideHttpClient } from '@angular/common/http' -import { - provideTanStackQuery, - QueryClient, -} from '@tanstack/angular-query-experimental' +import { bootstrapApplication } from '@angular/platform-browser' +import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query' -@NgModule({ - declarations: [AppComponent], - imports: [BrowserModule], - providers: [provideTanStackQuery(new QueryClient())], - bootstrap: [AppComponent], +bootstrapApplication(AppComponent, { + providers: [ + provideHttpClient(), + provideTanStackQuery(() => new QueryClient()), + ], }) -export class AppModule {} ``` ### Component with query and mutation @@ -52,7 +35,7 @@ import { injectMutation, injectQuery, QueryClient, -} from '@tanstack/angular-query-experimental' +} from '@tanstack/angular-query' @Component({ template: ` diff --git a/docs/framework/angular/reference/functions/infiniteQueryOptions.md b/docs/framework/angular/reference/functions/infiniteQueryOptions.md index 38986e086e8..f1165075bbe 100644 --- a/docs/framework/angular/reference/functions/infiniteQueryOptions.md +++ b/docs/framework/angular/reference/functions/infiniteQueryOptions.md @@ -9,7 +9,7 @@ title: infiniteQueryOptions function infiniteQueryOptions(options: DefinedInitialDataInfiniteOptions): CreateInfiniteQueryOptions & object & QueryKeyWithDataTag, TError>; ``` -Defined in: [packages/angular-query-experimental/src/infinite-query-options.ts:181](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L181) +Defined in: [packages/angular-query/src/infinite-query-options.ts:87](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L87) You can generally pass everything to `infiniteQueryOptions` that you can also pass to `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as @@ -51,7 +51,7 @@ The [DefinedInitialDataInfiniteOptions](../type-aliases/DefinedInitialDataInfini ### Returns -The same options object, typed so that `queryKey` carries the inferred data type. +[`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `InfiniteData`\<`TQueryFnData`, `unknown`\>, `TError`\> ### See @@ -100,7 +100,7 @@ export class Projects { function infiniteQueryOptions(options: UnusedSkipTokenInfiniteOptions): OmitKeyof, "queryFn"> & object & QueryKeyWithDataTag, TError>; ``` -Defined in: [packages/angular-query-experimental/src/infinite-query-options.ts:255](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L255) +Defined in: [packages/angular-query/src/infinite-query-options.ts:117](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L117) You can generally pass everything to `infiniteQueryOptions` that you can also pass to `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as @@ -140,7 +140,7 @@ The [UnusedSkipTokenInfiniteOptions](../type-aliases/UnusedSkipTokenInfiniteOpti ### Returns -The same options object, typed so that `queryKey` carries the inferred data type. +`OmitKeyof`\<[`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>, `"queryFn"`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `InfiniteData`\<`TQueryFnData`, `unknown`\>, `TError`\> ### Remarks @@ -195,7 +195,7 @@ export class Comments { function infiniteQueryOptions(options: UndefinedInitialDataInfiniteOptions): CreateInfiniteQueryOptions & object & QueryKeyWithDataTag, TError>; ``` -Defined in: [packages/angular-query-experimental/src/infinite-query-options.ts:329](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L329) +Defined in: [packages/angular-query/src/infinite-query-options.ts:147](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L147) You can generally pass everything to `infiniteQueryOptions` that you can also pass to `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as @@ -235,7 +235,7 @@ The [UndefinedInitialDataInfiniteOptions](../type-aliases/UndefinedInitialDataIn ### Returns -The same options object, typed so that `queryKey` carries the inferred data type. +[`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `InfiniteData`\<`TQueryFnData`, `unknown`\>, `TError`\> ### Remarks diff --git a/docs/framework/angular/reference/functions/injectInfiniteQuery.md b/docs/framework/angular/reference/functions/injectInfiniteQuery.md index 39aecc1d173..def9d593971 100644 --- a/docs/framework/angular/reference/functions/injectInfiniteQuery.md +++ b/docs/framework/angular/reference/functions/injectInfiniteQuery.md @@ -3,20 +3,26 @@ id: injectInfiniteQuery title: injectInfiniteQuery --- +# Function: injectInfiniteQuery() + +Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key. +Infinite queries can additively "load more" data onto an existing set of data or support infinite scroll. + +## Param + +A function that returns infinite query options. + +## See + +https://tanstack.com/query/latest/docs/framework/angular/guides/infinite-queries + ## Call Signature ```ts -function injectInfiniteQuery(injectInfiniteQueryFn: () => DefinedInitialDataInfiniteOptions, options?: InjectInfiniteQueryOptions): DefinedCreateInfiniteQueryResult; +function injectInfiniteQuery(optionsFn): DefinedCreateInfiniteQueryResult; ``` -Defined in: [packages/angular-query-experimental/src/inject-infinite-query.ts:83](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L83) - -The options for `injectInfiniteQuery` are identical to `injectQuery`, with the addition of -`initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. Infinite queries can -additively "load more" data onto an existing set of data, or "infinite scroll". - -This overload is selected when `initialData` is set on the options returned by `injectInfiniteQueryFn`, -so the resulting `data` signal is never `undefined` (unless a `select` changes `TData` to include `undefined`). +Defined in: [packages/angular-query/src/inject-infinite-query.ts:27](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-infinite-query.ts#L27) ### Type Parameters @@ -42,79 +48,21 @@ so the resulting `data` signal is never `undefined` (unless a `select` changes ` ### Parameters -#### injectInfiniteQueryFn +#### optionsFn () => [`DefinedInitialDataInfiniteOptions`](../type-aliases/DefinedInitialDataInfiniteOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> -A function returning the [DefinedInitialDataInfiniteOptions](../type-aliases/DefinedInitialDataInfiniteOptions.md) to use — -everything you can pass to `injectInfiniteQuery`, with `initialData` set. Similar to `computed` from -Angular, this function runs in the reactive context, so signals read inside it drive the query. - -#### options? - -[`InjectInfiniteQueryOptions`](../interfaces/InjectInfiniteQueryOptions.md) - -Additional configuration. - ### Returns [`DefinedCreateInfiniteQueryResult`](../type-aliases/DefinedCreateInfiniteQueryResult.md)\<`TData`, `TError`\> -The same signals as `injectQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, -`hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and -`data().pageParams` are also added, as long as a `select` doesn't change `TData` away from its default -`InfiniteData` shape. - -### Remarks - -Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default -refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user -actions, or add conditions like `hasNextPage() && !isFetching()`. - -### See - -[infiniteQueryOptions](infiniteQueryOptions.md) to share these options between `injectInfiniteQuery` and imperative APIs -like `queryClient.fetchInfiniteQuery`. - -### Example - -```angular-ts -@Component({ - selector: 'projects', - template: ` - -
    - @for (page of projectsQuery.data().pages; track $index) { - @for (project of page.projects; track project.id) { -
  • {{ project.name }}
  • - } - } -
- `, -}) -export class Projects { - readonly projectsQuery = injectInfiniteQuery(() => ({ - queryKey: ['projects'], - queryFn: ({ pageParam }) => fetchProjects(pageParam), - initialPageParam: 0, - getNextPageParam: (lastPage) => lastPage.nextId, - initialData: { pages: [], pageParams: [] }, - })) -} -``` - ## Call Signature ```ts -function injectInfiniteQuery(injectInfiniteQueryFn: () => UndefinedInitialDataInfiniteOptions, options?: InjectInfiniteQueryOptions): CreateInfiniteQueryResult; +function injectInfiniteQuery(optionsFn): CreateInfiniteQueryResult; ``` -Defined in: [packages/angular-query-experimental/src/inject-infinite-query.ts:239](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L239) - -Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a -unique key. Infinite queries can additively "load more" data onto an existing set of data, or -"infinite scroll". +Defined in: [packages/angular-query/src/inject-infinite-query.ts:43](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-infinite-query.ts#L43) ### Type Parameters @@ -140,171 +88,21 @@ unique key. Infinite queries can additively "load more" data onto an existing se ### Parameters -#### injectInfiniteQueryFn +#### optionsFn () => [`UndefinedInitialDataInfiniteOptions`](../type-aliases/UndefinedInitialDataInfiniteOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> -A function returning the [UndefinedInitialDataInfiniteOptions](../type-aliases/UndefinedInitialDataInfiniteOptions.md) to use -— everything you can pass to `injectInfiniteQuery`. Similar to `computed` from Angular, this function runs -in the reactive context, so signals read inside it drive the query. - -#### options? - -[`InjectInfiniteQueryOptions`](../interfaces/InjectInfiniteQueryOptions.md) - -Additional configuration. - ### Returns [`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\<`TData`, `TError`\> -The same signals as `injectQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, -`hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and -`data().pageParams` are also added, as long as a `select` doesn't change `TData` away from its default -`InfiniteData` shape. - -### Remarks - -Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default -refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user -actions, or add conditions like `hasNextPage() && !isFetching()`. This is the only overload that accepts -`queryFn: skipToken`, shown below. - -### See - -[infiniteQueryOptions](infiniteQueryOptions.md) to share these options between `injectInfiniteQuery` and imperative APIs -like `queryClient.fetchInfiniteQuery`. - -### Examples - -Fetching the next page from a button click: -```angular-ts -@Component({ - selector: 'projects-list', - template: ` -
    - @for (page of projectsQuery.data()?.pages; track $index) { - @for (project of page.projects; track project.id) { -
  • {{ project.name }}
  • - } - } -
- - `, -}) -export class ProjectsList { - readonly projectsQuery = injectInfiniteQuery(() => ({ - queryKey: ['projects'], - queryFn: ({ pageParam }) => fetchProjects(pageParam), - initialPageParam: 0, - getNextPageParam: (lastPage) => lastPage.nextId, - })) -} -``` - -Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a sentinel -element after the list: -```angular-ts -@Component({ - selector: 'projects-list', - template: ` -
    - @for (page of projectsQuery.data()?.pages; track $index) { - @for (project of page.projects; track project.id) { -
  • {{ project.name }}
  • - } - } -
-
{{ projectsQuery.isFetchingNextPage() ? 'Loading more...' : '' }}
- `, -}) -export class ProjectsList { - readonly sentinel = viewChild>('sentinel') - - readonly projectsQuery = injectInfiniteQuery(() => ({ - queryKey: ['projects'], - queryFn: ({ pageParam }) => fetchProjects(pageParam), - initialPageParam: 0, - getNextPageParam: (lastPage) => lastPage.nextId, - })) - - constructor() { - effect((onCleanup) => { - const sentinel = this.sentinel()?.nativeElement - if ( - sentinel == null || - !this.projectsQuery.hasNextPage() || - this.projectsQuery.isFetching() - ) { - return - } - - const observer = new IntersectionObserver(([entry]) => { - if (entry?.isIntersecting) this.projectsQuery.fetchNextPage() - }) - observer.observe(sentinel) - - onCleanup(() => observer.disconnect()) - }) - } -} -``` - -A query that's disabled, type safe, until `postId` is set — pass `skipToken` as `queryFn` instead of -setting `enabled: false`: -```angular-ts -@Component({ - selector: 'comments', - template: ` - @if (postId() == null) { - Select a post - } @else if (commentsQuery.isPending()) { - Loading... - } @else if (commentsQuery.isError()) { - Error: {{ commentsQuery.error()?.message }} - } @else { -
    - @for (page of commentsQuery.data().pages; track $index) { - @for (comment of page.comments; track comment.id) { -
  • {{ comment.text }}
  • - } - } -
- } - `, -}) -export class Comments { - readonly postId = signal(undefined) - - readonly commentsQuery = injectInfiniteQuery(() => ({ - queryKey: ['post', this.postId(), 'comments'], - queryFn: - this.postId() != null - ? ({ pageParam }) => fetchComments(this.postId()!, pageParam) - : skipToken, - initialPageParam: 0, - getNextPageParam: (lastPage) => lastPage.nextId, - })) -} -``` - ## Call Signature ```ts -function injectInfiniteQuery(injectInfiniteQueryFn: () => CreateInfiniteQueryOptions, options?: InjectInfiniteQueryOptions): CreateInfiniteQueryResult; +function injectInfiniteQuery(optionsFn): CreateInfiniteQueryResult; ``` -Defined in: [packages/angular-query-experimental/src/inject-infinite-query.ts:267](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L267) - -This overload accepts the general [CreateInfiniteQueryOptions](../interfaces/CreateInfiniteQueryOptions.md) shape rather than the -`initialData`-aware overloads above, so whether `data` is defined can't be inferred from the call site — -useful when wrapping `injectInfiniteQuery` in your own helper function that forwards caller-provided -options. +Defined in: [packages/angular-query/src/inject-infinite-query.ts:59](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-infinite-query.ts#L59) ### Type Parameters @@ -330,21 +128,10 @@ options. ### Parameters -#### injectInfiniteQueryFn +#### optionsFn () => [`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> -A function that returns infinite query options. Similar to `computed` from -Angular, this function runs in the reactive context, so signals read inside it drive the query. - -#### options? - -[`InjectInfiniteQueryOptions`](../interfaces/InjectInfiniteQueryOptions.md) - -Additional configuration. - ### Returns [`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\<`TData`, `TError`\> - -The infinite query result. diff --git a/docs/framework/angular/reference/functions/injectIsFetching.md b/docs/framework/angular/reference/functions/injectIsFetching.md index ce629a0cf3f..48a8aafe436 100644 --- a/docs/framework/angular/reference/functions/injectIsFetching.md +++ b/docs/framework/angular/reference/functions/injectIsFetching.md @@ -4,27 +4,21 @@ title: injectIsFetching --- ```ts -function injectIsFetching(filters?: QueryFilters, options?: InjectIsFetchingOptions): Signal; +function injectIsFetching(filters): Signal; ``` -Defined in: [packages/angular-query-experimental/src/inject-is-fetching.ts:63](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-fetching.ts#L63) +Defined in: [packages/angular-query/src/inject-is-fetching.ts:15](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-is-fetching.ts#L15) Injects a signal that tracks the number of queries that your application is loading or fetching in the background (useful for app-wide loading indicators). ## Parameters -### filters? +### filters -[`QueryFilters`](../interfaces/QueryFilters.md)\ +() => `QueryFilters` -The [QueryFilters](../interfaces/QueryFilters.md) to narrow down the matched queries. - -### options? - -[`InjectIsFetchingOptions`](../interfaces/InjectIsFetchingOptions.md) - -Additional configuration +A reactive factory for the filters. ## Returns diff --git a/docs/framework/angular/reference/functions/injectIsMutating.md b/docs/framework/angular/reference/functions/injectIsMutating.md index 409d7c1653f..c674046a97b 100644 --- a/docs/framework/angular/reference/functions/injectIsMutating.md +++ b/docs/framework/angular/reference/functions/injectIsMutating.md @@ -4,27 +4,21 @@ title: injectIsMutating --- ```ts -function injectIsMutating(filters?: MutationFilters, options?: InjectIsMutatingOptions): Signal; +function injectIsMutating(filters): Signal; ``` -Defined in: [packages/angular-query-experimental/src/inject-is-mutating.ts:46](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-mutating.ts#L46) +Defined in: [packages/angular-query/src/inject-is-mutating.ts:14](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-is-mutating.ts#L14) Injects a signal that tracks the number of mutations that your application currently has `pending` (useful for app-wide loading indicators). ## Parameters -### filters? +### filters -[`MutationFilters`](../interfaces/MutationFilters.md)\<`unknown`, `Error`, `unknown`, `unknown`\> +() => `MutationFilters` -The [MutationFilters](../interfaces/MutationFilters.md) to narrow down the matched mutations. - -### options? - -[`InjectIsMutatingOptions`](../interfaces/InjectIsMutatingOptions.md) - -Additional configuration +A reactive factory for the filters. ## Returns diff --git a/docs/framework/angular/reference/functions/injectIsRestoring.md b/docs/framework/angular/reference/functions/injectIsRestoring.md index 2fbe1dfee3a..627aad15b52 100644 --- a/docs/framework/angular/reference/functions/injectIsRestoring.md +++ b/docs/framework/angular/reference/functions/injectIsRestoring.md @@ -4,22 +4,12 @@ title: injectIsRestoring --- ```ts -function injectIsRestoring(options?: InjectIsRestoringOptions): Signal; +function injectIsRestoring(): Signal; ``` -Defined in: [packages/angular-query-experimental/src/inject-is-restoring.ts:35](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-restoring.ts#L35) +Defined in: [packages/angular-query/src/inject-is-restoring.ts:22](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-is-restoring.ts#L22) -Injects a signal that tracks whether a restore (e.g. from a persisted client, wired up via -`provideIsRestoring`) is currently in progress. `injectQuery` and friends also check this internally to -avoid race conditions between the restore and initializing queries. - -## Parameters - -### options? - -`InjectIsRestoringOptions` - -Additional configuration +Returns a readonly signal that is true while the persistence integration restores cached query data. It is false when no restoration is in progress. ## Returns diff --git a/docs/framework/angular/reference/functions/injectMutation.md b/docs/framework/angular/reference/functions/injectMutation.md index 2a31bca1e7d..a4050838d76 100644 --- a/docs/framework/angular/reference/functions/injectMutation.md +++ b/docs/framework/angular/reference/functions/injectMutation.md @@ -4,10 +4,10 @@ title: injectMutation --- ```ts -function injectMutation(injectMutationFn: () => CreateMutationOptions, options?: InjectMutationOptions): CreateMutationResult; +function injectMutation(optionsFn): CreateMutationResult; ``` -Defined in: [packages/angular-query-experimental/src/inject-mutation.ts:174](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation.ts#L174) +Defined in: [packages/angular-query/src/inject-mutation.ts:28](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-mutation.ts#L28) Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. `injectMutation` is the function for that. Unlike queries, mutations are not run automatically. @@ -32,19 +32,13 @@ Unlike queries, mutations are typically used to create/update/delete data or per ## Parameters -### injectMutationFn +### optionsFn () => [`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\> A function that returns mutation options. Similar to `computed` from Angular, this function runs in the reactive context, so signals read inside it drive the mutation's options. -### options? - -[`InjectMutationOptions`](../interfaces/InjectMutationOptions.md) - -Additional configuration - ## Returns [`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\> diff --git a/docs/framework/angular/reference/functions/injectMutationState.md b/docs/framework/angular/reference/functions/injectMutationState.md index 2e43406cfee..2b14f5046e5 100644 --- a/docs/framework/angular/reference/functions/injectMutationState.md +++ b/docs/framework/angular/reference/functions/injectMutationState.md @@ -4,10 +4,10 @@ title: injectMutationState --- ```ts -function injectMutationState(injectMutationStateFn: () => MutationStateOptions, options?: InjectMutationStateOptions): Signal; +function injectMutationState(options): Signal; ``` -Defined in: [packages/angular-query-experimental/src/inject-mutation-state.ts:106](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation-state.ts#L106) +Defined in: [packages/angular-query/src/inject-mutation-state.ts:55](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-mutation-state.ts#L55) Injects a signal that gives you access to all mutations in the `MutationCache`. You can pass `filters` ([MutationFilters](../interfaces/MutationFilters.md)) to narrow down your mutations, and `select` to transform the mutation state. @@ -18,22 +18,20 @@ Injects a signal that gives you access to all mutations in the `MutationCache`. `TResult` = [`MutationState`](../interfaces/MutationState.md)\<`unknown`, `Error`, `unknown`, `unknown`\> +### TMutation + +`TMutation` *extends* `Mutation`\<`any`, `any`, `any`, `any`\> = `MutationTypeFromResult`\<`TResult`\> + ## Parameters -### injectMutationStateFn +### options -() => `MutationStateOptions`\<`TResult`\> +() => [`MutationStateOptions`](../type-aliases/MutationStateOptions.md)\<`TResult`, `TMutation`\> A function returning the `filters` to narrow down matched mutations, and an optional `select` to transform the mutation state. Similar to `computed` from Angular, this function runs in the reactive context, so signals read inside it re-narrow the matched mutations. -### options? - -[`InjectMutationStateOptions`](../interfaces/InjectMutationStateOptions.md) - -Additional configuration - ## Returns `Signal`\<`TResult`[]\> diff --git a/docs/framework/angular/reference/functions/injectQueries.md b/docs/framework/angular/reference/functions/injectQueries.md new file mode 100644 index 00000000000..f07d91a2b71 --- /dev/null +++ b/docs/framework/angular/reference/functions/injectQueries.md @@ -0,0 +1,49 @@ +--- +id: injectQueries +title: injectQueries +--- + +```ts +function injectQueries(optionsFn): Signal; +``` + +Defined in: [packages/angular-query/src/inject-queries.ts:43](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-queries.ts#L43) + +Injects multiple queries that run in parallel and react to Angular signals. + +```ts +class UsersComponent { + readonly users = input.required>() + + readonly userQueries = injectQueries(() => ({ + queries: this.users().map((user) => ({ + queryKey: ['user', user.id], + queryFn: () => fetchUserById(user.id), + })), + })) +} +``` + +## Type Parameters + +### T + +`T` *extends* `any`[] + +### TCombinedResult + +`TCombinedResult` = `T` *extends* \[\] ? \[\] : `T` *extends* \[`Head`\] ? \[`GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<`Head`\>\[`"data"`\], [`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>, [`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>\>\] : `T` *extends* \[`Head`, `...Tails[]`\] ? \[`...Tails[]`\] *extends* \[\] ? \[\] : \[`...Tails[]`\] *extends* \[`Head`\] ? \[`GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<`Head`\>\[`"data"`\], [`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>, [`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>\>, `GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<`Head`\>\[`"data"`\], [`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>, [`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>\>\] : \[`...Tails[]`\] *extends* \[`Head`, `...Tails[]`\] ? \[`...Tails[]`\] *extends* \[\] ? \[\] : \[`...Tails[]`\] *extends* \[`Head`\] ? \[`GenericGetDefinedOrUndefinedQueryResult`\<`Head`, ...\[...\], [`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<..., ...\>, [`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<..., ...\>\>, `GenericGetDefinedOrUndefinedQueryResult`\<`Head`, ...\[...\], [`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<..., ...\>, [`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<..., ...\>\>, `GenericGetDefinedOrUndefinedQueryResult`\<`Head`, ...\[...\], [`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<..., ...\>, [`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<..., ...\>\>\] : \[`...Tails[]`\] *extends* \[`Head`, `...Tails[]`\] ? \[`...(...)[]`\] *extends* \[\] ? \[\] : ... *extends* ... ? ... : ... : \[`...{ [K in (...)]: (...) }[]`\] : \[...\{ \[K in string \| number \| symbol\]: GenericGetDefinedOrUndefinedQueryResult\\], InferDataAndError\<(...)\>\["data"\], CreateQueryResult\<(...)\[(...)\], (...)\[(...)\]\>, DefinedCreateQueryResult\<(...)\[(...)\], (...)\[(...)\]\>\> \}\[\]\] : \{ \[K in string \| number \| symbol\]: GenericGetDefinedOrUndefinedQueryResult\\], InferDataAndError\\]\>\["data"\], CreateQueryResult\\]\>\["data"\], InferDataAndError\\]\>\["error"\]\>, DefinedCreateQueryResult\\]\>\["data"\], InferDataAndError\\]\>\["error"\]\>\> \} + +## Parameters + +### optionsFn + +() => [`InjectQueriesOptions`](../interfaces/InjectQueriesOptions.md)\<`T`, `TCombinedResult`\> + +A function that returns queries' options. + +## Returns + +`Signal`\<`TCombinedResult`\> + +A signal containing the query results in the same order as the input queries. diff --git a/docs/framework/angular/reference/functions/injectQuery.md b/docs/framework/angular/reference/functions/injectQuery.md index bf715335bf4..860e5ddc567 100644 --- a/docs/framework/angular/reference/functions/injectQuery.md +++ b/docs/framework/angular/reference/functions/injectQuery.md @@ -3,16 +3,58 @@ id: injectQuery title: injectQuery --- -## Call Signature +# Function: injectQuery() + +Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. + +**Basic example** +```ts +import { lastValueFrom } from 'rxjs' + +class ServiceOrComponent { + query = injectQuery(() => ({ + queryKey: ['repoData'], + queryFn: () => + lastValueFrom( + this.#http.get('https://api.github.com/repos/tanstack/query'), + ), + })) +} +``` + +Similar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context. +In the example below, the query will be automatically enabled and executed when the filter signal changes +to a truthy value. When the filter signal changes back to a falsy value, the query will be disabled. +**Reactive example** ```ts -function injectQuery(injectQueryFn: () => DefinedInitialDataOptions, options?: InjectQueryOptions): DefinedCreateQueryResult; +class ServiceOrComponent { + filter = signal('') + + todosQuery = injectQuery(() => ({ + queryKey: ['todos', this.filter()], + queryFn: () => fetchTodos(this.filter()), + // Signals can be combined with expressions + enabled: !!this.filter(), + })) +} ``` -Defined in: [packages/angular-query-experimental/src/inject-query.ts:69](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L69) +## Param -This overload is selected when `initialData` is set on the options returned by `injectQueryFn`, so the -resulting `data` signal is never `undefined` (unless a `select` changes `TData` to include `undefined`). +A function that returns query options. + +## See + +https://tanstack.com/query/latest/docs/framework/angular/guides/queries + +## Call Signature + +```ts +function injectQuery(optionsFn): DefinedCreateQueryResult; +``` + +Defined in: [packages/angular-query/src/inject-query.ts:17](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-query.ts#L17) ### Type Parameters @@ -34,69 +76,21 @@ resulting `data` signal is never `undefined` (unless a `select` changes `TData` ### Parameters -#### injectQueryFn +#### optionsFn () => [`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> -A function returning the [DefinedInitialDataOptions](../type-aliases/DefinedInitialDataOptions.md) to use — everything you -can pass to `injectQuery`, with `initialData` set. Similar to `computed` from Angular, this function runs -in the reactive context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive the query. - -#### options? - -[`InjectQueryOptions`](../interfaces/InjectQueryOptions.md) - -Additional configuration - ### Returns [`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<`TData`, `TError`\> -The query result, typed so that `data` is never `undefined` (unless a `select` changes `TData` to -include `undefined`). - -### See - - - https://tanstack.com/query/latest/docs/framework/angular/guides/queries - - [queryOptions](queryOptions.md) to share these options between `injectQuery` and imperative APIs like -`queryClient.fetchQuery`. - -### Example - -```angular-ts -@Component({ - selector: 'posts', - template: ` - - @if (postsQuery.isError()) { - Error: {{ postsQuery.error()?.message }} - } -
    - @for (post of postsQuery.data(); track post.id) { -
  • {{ post.title }}
  • - } -
- `, -}) -export class Posts { - readonly postsQuery = injectQuery(() => ({ - queryKey: ['posts'], - queryFn: fetchPosts, - initialData: [], - })) -} -``` - ## Call Signature ```ts -function injectQuery(injectQueryFn: () => UndefinedInitialDataOptions, options?: InjectQueryOptions): CreateQueryResult; +function injectQuery(optionsFn): CreateQueryResult; ``` -Defined in: [packages/angular-query-experimental/src/inject-query.ts:158](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L158) - -Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. +Defined in: [packages/angular-query/src/inject-query.ts:31](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-query.ts#L31) ### Type Parameters @@ -118,105 +112,21 @@ Injects a query: a declarative dependency on an asynchronous source of data that ### Parameters -#### injectQueryFn +#### optionsFn () => [`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> -A function returning the [UndefinedInitialDataOptions](../type-aliases/UndefinedInitialDataOptions.md) to use — everything -you can pass to `injectQuery`. Similar to `computed` from Angular, this function runs in the reactive -context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive the query. - -#### options? - -[`InjectQueryOptions`](../interfaces/InjectQueryOptions.md) - -Additional configuration - ### Returns [`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<`TData`, `TError`\> -The query result. `status()` is `'pending'` if there is no cached data to display, `'error'` if -the last fetch attempt failed, or `'success'` if the query has data to display. `isPending`/`isSuccess`/ -`isError` are type-guard methods for convenience. - -### See - - - https://tanstack.com/query/latest/docs/framework/angular/guides/queries - - [queryOptions](queryOptions.md) to share these options between `injectQuery` and imperative APIs like -`queryClient.fetchQuery`. - -### Examples - -```angular-ts -@Component({ - selector: 'posts', - template: ` - @if (postsQuery.isPending()) { - Loading... - } @else if (postsQuery.isError()) { - Error: {{ postsQuery.error()?.message }} - } @else { -
    - @for (post of postsQuery.data(); track post.id) { -
  • {{ post.title }}
  • - } -
- } - `, -}) -export class Posts { - readonly postsQuery = injectQuery(() => ({ - queryKey: ['posts'], - queryFn: fetchPosts, - })) -} -``` - -Similar to `computed` from Angular, the function passed to `injectQuery` runs in the reactive context. In -the example below, the query is automatically enabled and executed when the filter signal changes to a -truthy value. When the filter signal changes back to a falsy value, the query is disabled. -```angular-ts -@Component({ - selector: 'posts', - template: ` - - @if (postsQuery.isPending()) { - Loading... - } @else if (postsQuery.isError()) { - Error: {{ postsQuery.error()?.message }} - } @else { -
    - @for (post of postsQuery.data(); track post.id) { -
  • {{ post.title }}
  • - } -
- } - `, -}) -export class Posts { - readonly filter = signal('') - - readonly postsQuery = injectQuery(() => ({ - queryKey: ['posts', this.filter()], - queryFn: () => fetchPosts(this.filter()), - // Signals can be combined with expressions - enabled: !!this.filter(), - })) -} -``` - ## Call Signature ```ts -function injectQuery(injectQueryFn: () => CreateQueryOptions, options?: InjectQueryOptions): CreateQueryResult; +function injectQuery(optionsFn): CreateQueryResult; ``` -Defined in: [packages/angular-query-experimental/src/inject-query.ts:185](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L185) - -This overload accepts the general [CreateQueryOptions](../interfaces/CreateQueryOptions.md) shape rather than the `initialData`-aware -overloads above, so whether `data` is defined can't be inferred from the call site — useful when wrapping -`injectQuery` in your own helper function that forwards caller-provided options. +Defined in: [packages/angular-query/src/inject-query.ts:45](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-query.ts#L45) ### Type Parameters @@ -238,26 +148,10 @@ overloads above, so whether `data` is defined can't be inferred from the call si ### Parameters -#### injectQueryFn - -() => [`CreateQueryOptions`](../interfaces/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> +#### optionsFn -A function that returns query options. Similar to `computed` from Angular, this -function runs in the reactive context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive -the query. - -#### options? - -[`InjectQueryOptions`](../interfaces/InjectQueryOptions.md) - -Additional configuration +() => [`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> ### Returns [`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<`TData`, `TError`\> - -The query result. - -### See - -https://tanstack.com/query/latest/docs/framework/angular/guides/queries diff --git a/docs/framework/angular/reference/functions/injectQueryClient.md b/docs/framework/angular/reference/functions/injectQueryClient.md deleted file mode 100644 index ba1298a498c..00000000000 --- a/docs/framework/angular/reference/functions/injectQueryClient.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: injectQueryClient -title: injectQueryClient ---- - -```ts -function injectQueryClient(injectOptions: InjectOptions & object): QueryClient; -``` - -Defined in: [packages/angular-query-experimental/src/inject-query-client.ts:18](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query-client.ts#L18) - -Injects a `QueryClient` instance and allows passing a custom injector. - -## Parameters - -### injectOptions - -`InjectOptions` & `object` = `{}` - -Type of the options argument to inject and optionally a custom injector. - -## Returns - -[`QueryClient`](../classes/QueryClient.md) - -The `QueryClient` instance. - -## Deprecated - -Use `inject(QueryClient)` instead. -If you need to get a `QueryClient` from a custom injector, use `injector.get(QueryClient)`. - -**Example** -```ts -const queryClient = injectQueryClient(); -``` diff --git a/docs/framework/angular/reference/functions/mutationOptions.md b/docs/framework/angular/reference/functions/mutationOptions.md index fd29abb7ac6..813132819b0 100644 --- a/docs/framework/angular/reference/functions/mutationOptions.md +++ b/docs/framework/angular/reference/functions/mutationOptions.md @@ -9,7 +9,7 @@ title: mutationOptions function mutationOptions(options: WithRequired, "mutationKey">): WithRequired, "mutationKey">; ``` -Defined in: [packages/angular-query-experimental/src/mutation-options.ts:40](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/mutation-options.ts#L40) +Defined in: [packages/angular-query/src/mutation-options.ts:39](https://github.com/TanStack/query/blob/main/packages/angular-query/src/mutation-options.ts#L39) You can generally pass everything to `mutationOptions` that you can also pass to `injectMutation`. A `mutationKey` is required on this overload so the mutation can be looked up later, e.g. with @@ -85,7 +85,7 @@ export class SavingIndicator { function mutationOptions(options: Omit, "mutationKey">): Omit, "mutationKey">; ``` -Defined in: [packages/angular-query-experimental/src/mutation-options.ts:98](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/mutation-options.ts#L98) +Defined in: [packages/angular-query/src/mutation-options.ts:53](https://github.com/TanStack/query/blob/main/packages/angular-query/src/mutation-options.ts#L53) You can generally pass everything to `mutationOptions` that you can also pass to `injectMutation`. No `mutationKey` is required on this overload — use this when you don't need to target the mutation via a diff --git a/docs/framework/angular/reference/functions/provideAngularQuery.md b/docs/framework/angular/reference/functions/provideAngularQuery.md deleted file mode 100644 index e27f01bb256..00000000000 --- a/docs/framework/angular/reference/functions/provideAngularQuery.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: provideAngularQuery -title: provideAngularQuery ---- - -```ts -function provideAngularQuery(queryClient: QueryClient): Provider[]; -``` - -Defined in: [packages/angular-query-experimental/src/providers.ts:121](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L121) - -Sets up providers necessary to enable TanStack Query functionality for Angular applications. - -Allows configuring a `QueryClient`. - -## Parameters - -### queryClient - -[`QueryClient`](../classes/QueryClient.md) - -A `QueryClient` instance. - -## Returns - -`Provider`[] - -A set of providers to set up TanStack Query. - -## See - -https://tanstack.com/query/v5/docs/framework/angular/quick-start - -## Deprecated - -Use `provideTanStackQuery` instead. diff --git a/docs/framework/angular/reference/functions/provideIsRestoring.md b/docs/framework/angular/reference/functions/provideIsRestoring.md deleted file mode 100644 index 877793236da..00000000000 --- a/docs/framework/angular/reference/functions/provideIsRestoring.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -id: provideIsRestoring -title: provideIsRestoring ---- - -```ts -function provideIsRestoring(isRestoring: Signal): Provider; -``` - -Defined in: [packages/angular-query-experimental/src/inject-is-restoring.ts:48](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-restoring.ts#L48) - -Registers a provider for the restore state read by `injectIsRestoring`. Wire this up wherever you drive a -restore yourself — e.g. a persist-client integration — so `injectQuery` and friends can defer subscribing -to their observer (avoiding a race with the restore) until the restore signal flips back to `false`. - -## Parameters - -### isRestoring - -`Signal`\<`boolean`\> - -A readonly `Signal` that tracks the restore state. - -## Returns - -`Provider` - -A provider for the `isRestoring` signal. diff --git a/docs/framework/angular/reference/functions/provideQueryClient.md b/docs/framework/angular/reference/functions/provideQueryClient.md deleted file mode 100644 index 8540552f034..00000000000 --- a/docs/framework/angular/reference/functions/provideQueryClient.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -id: provideQueryClient -title: provideQueryClient ---- - -```ts -function provideQueryClient(queryClient: - | QueryClient - | InjectionToken): Provider; -``` - -Defined in: [packages/angular-query-experimental/src/providers.ts:22](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L22) - -Usually [provideTanStackQuery](provideTanStackQuery.md) is used once to set up TanStack Query and the -[`QueryClient`](https://tanstack.com/query/latest/docs/reference/QueryClient) for the entire application — -it calls `provideQueryClient` internally. Use `provideQueryClient` directly to provide a different -`QueryClient` instance for part of the application, or for unit testing. - -## Parameters - -### queryClient - -A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`. - -[`QueryClient`](../classes/QueryClient.md) | `InjectionToken`\<[`QueryClient`](../classes/QueryClient.md)\> - -## Returns - -`Provider` - -A provider object that can be used to provide the `QueryClient` instance. - -## Example - -Providing a test-only `QueryClient` in a component test, without wiring up `provideTanStackQuery`'s other -defaults: -```ts -TestBed.configureTestingModule({ - providers: [provideQueryClient(new QueryClient())], -}) -``` diff --git a/docs/framework/angular/reference/functions/provideTanStackQuery.md b/docs/framework/angular/reference/functions/provideTanStackQuery.md index d80b8bc9c11..e50e8e9f560 100644 --- a/docs/framework/angular/reference/functions/provideTanStackQuery.md +++ b/docs/framework/angular/reference/functions/provideTanStackQuery.md @@ -4,87 +4,74 @@ title: provideTanStackQuery --- ```ts -function provideTanStackQuery(queryClient: - | QueryClient - | InjectionToken, ...features: QueryFeatures[]): Provider[]; +function provideTanStackQuery(queryClientFactory, ...features): EnvironmentProviders; ``` -Defined in: [packages/angular-query-experimental/src/providers.ts:102](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L102) +Defined in: [packages/angular-query/src/providers.ts:99](https://github.com/TanStack/query/blob/main/packages/angular-query/src/providers.ts#L99) -Sets up providers necessary to enable TanStack Query functionality for Angular applications. Allows -configuring a `QueryClient` and optional features such as developer tools. +Provides a `QueryClient` and optional TanStack Query features. +The factory runs once per injector in Angular's injection context, so it can +call `inject()` and each SSR request can receive an independent cache. -## Parameters - -### queryClient - -A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`. - -[`QueryClient`](../classes/QueryClient.md) | `InjectionToken`\<[`QueryClient`](../classes/QueryClient.md)\> - -### features - -...[`QueryFeatures`](../type-aliases/QueryFeatures.md)[] - -Optional features to configure additional Query functionality. - -## Returns - -`Provider`[] - -A set of providers to set up TanStack Query. - -## See - - - https://tanstack.com/query/v5/docs/framework/angular/quick-start - - withDevtools - -## Examples +**Example - standalone** ```ts -import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query-experimental' +import { + provideTanStackQuery, + QueryClient, +} from '@tanstack/angular-query' bootstrapApplication(AppComponent, { - providers: [provideTanStackQuery(new QueryClient())], + providers: [provideTanStackQuery(() => new QueryClient())], }) ``` -The same, in an `NgModule`-based application: -```ts -import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query-experimental' +You can also enable optional developer tools by adding `withDevtools`. By +default the tools will then be loaded when your app is in development mode. -@NgModule({ - declarations: [AppComponent], - imports: [BrowserModule], - providers: [provideTanStackQuery(new QueryClient())], - bootstrap: [AppComponent], -}) -export class AppModule {} -``` - -Enabling optional developer tools by adding `withDevtools` — by default, the tools are then loaded when -your app is in development mode: ```ts -import { - provideTanStackQuery, - withDevtools, - QueryClient, -} from '@tanstack/angular-query-experimental' +import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' bootstrapApplication(AppComponent, { - providers: [provideTanStackQuery(new QueryClient(), withDevtools())], + providers: [ + provideTanStackQuery(() => new QueryClient(), withDevtools()), + ], }) ``` -Using an `InjectionToken` for the `QueryClient` — an advanced optimization that lets TanStack Query be -absent from the main application bundle, useful for including it on lazy-loaded routes only while still -sharing a `QueryClient`. This is a small optimization; for most applications it's preferable to provide -the `QueryClient` in the main application config, as in the examples above: +Resolve an existing token inside the factory when another provider owns client creation: + ```ts export const MY_QUERY_CLIENT = new InjectionToken('', { factory: () => new QueryClient(), }) -// In a lazy loaded route or lazy loaded component's providers array: -providers: [provideTanStackQuery(MY_QUERY_CLIENT)] +providers: [provideTanStackQuery(() => inject(MY_QUERY_CLIENT))] ``` + +## Parameters + +### queryClientFactory + +Creates or resolves a `QueryClient` in the injection context. + +() => `QueryClient` + +### features + +...readonly [`QueryFeature`](../interfaces/QueryFeature.md)[] + +Optional features to configure additional Query functionality. + +## Returns + +`EnvironmentProviders` + +A single EnvironmentProviders value (do not spread into `providers`). + +## See + + - https://tanstack.com/query/v5/docs/framework/angular/quick-start + - https://tanstack.com/query/v5/docs/framework/angular/devtools + - https://tanstack.com/query/latest/docs/framework/angular/guides/ssr diff --git a/docs/framework/angular/reference/functions/queryFeature.md b/docs/framework/angular/reference/functions/queryFeature.md deleted file mode 100644 index ac98f4c34f9..00000000000 --- a/docs/framework/angular/reference/functions/queryFeature.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -id: queryFeature -title: queryFeature ---- - -```ts -function queryFeature(kind: TFeatureKind, providers: Provider[]): QueryFeature; -``` - -Defined in: [packages/angular-query-experimental/src/providers.ts:143](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L143) - -Helper function to create an object that represents a Query feature. - -## Type Parameters - -### TFeatureKind - -`TFeatureKind` *extends* `"Devtools"` \| `"PersistQueryClient"` - -## Parameters - -### kind - -`TFeatureKind` - -The kind of feature, e.g. `'Devtools'`. - -### providers - -`Provider`[] - -The Angular providers this feature contributes to `provideTanStackQuery`. - -## Returns - -[`QueryFeature`](../interfaces/QueryFeature.md)\<`TFeatureKind`\> - -A Query feature. diff --git a/docs/framework/angular/reference/functions/queryOptions.md b/docs/framework/angular/reference/functions/queryOptions.md index 4b56bc8ffa7..e0902b6aa41 100644 --- a/docs/framework/angular/reference/functions/queryOptions.md +++ b/docs/framework/angular/reference/functions/queryOptions.md @@ -3,20 +3,35 @@ id: queryOptions title: queryOptions --- -## Call Signature +Allows sharing and re-using query options in a type-safe way. + +The `queryKey` will be tagged with the type from `queryFn`. + +**Example** ```ts -function queryOptions(options: DefinedInitialDataOptions): Omit, "queryFn"> & object & QueryKeyWithDataTag; + const { queryKey } = queryOptions({ + queryKey: ['key'], + queryFn: () => Promise.resolve(5), + // ^? Promise + }) + + const queryClient = new QueryClient() + const data = queryClient.getQueryData(queryKey) + // ^? number | undefined ``` -Defined in: [packages/angular-query-experimental/src/query-options.ts:151](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L151) +## Param -You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options -can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is -required and is the query key to generate options for. +The query options to tag with the type from `queryFn`. + +## Call Signature + +```ts +function queryOptions(options): CreateQueryOptions & object & QueryKeyWithDataTag; +``` -This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless -a `select` changes `TData` to include `undefined`). +Defined in: [packages/angular-query/src/query-options.ts:50](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L50) ### Type Parameters @@ -42,48 +57,9 @@ a `select` changes `TData` to include `undefined`). [`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> -The [DefinedInitialDataOptions](../type-aliases/DefinedInitialDataOptions.md) to use — everything you can pass to `injectQuery`, -with `initialData` set. - ### Returns -The same options object, typed so that `queryKey` carries the inferred data type. - -### See - - - [injectQuery](injectQuery.md) to run a query with these options. - - [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. - -### Example - -```angular-ts -import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' - -export const postsOptions = queryOptions({ - queryKey: ['posts'], - queryFn: fetchPosts, - initialData: [], -}) - -@Component({ - selector: 'posts', - template: ` - - @if (postsQuery.isError()) { - Error: {{ postsQuery.error()?.message }} - } -
    - @for (post of postsQuery.data(); track post.id) { -
  • {{ post.title }}
  • - } -
- `, -}) -export class Posts { - readonly postsQuery = injectQuery(() => postsOptions) -} -``` +[`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `TQueryFnData`, `TError`\> ## Call Signature @@ -91,11 +67,7 @@ export class Posts { function queryOptions(options: UnusedSkipTokenOptions): OmitKeyof, "queryFn"> & object & QueryKeyWithDataTag; ``` -Defined in: [packages/angular-query-experimental/src/query-options.ts:200](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L200) - -You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options -can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is -required and is the query key to generate options for. +Defined in: [packages/angular-query/src/query-options.ts:60](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L60) ### Type Parameters @@ -121,46 +93,9 @@ required and is the query key to generate options for. [`UnusedSkipTokenOptions`](../type-aliases/UnusedSkipTokenOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> -The [UnusedSkipTokenOptions](../type-aliases/UnusedSkipTokenOptions.md) to use — everything you can pass to `injectQuery`. - ### Returns -The same options object, typed so that `queryKey` carries the inferred data type. - -### See - - - [injectQuery](injectQuery.md) to run a query with these options. - - [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. - -### Example - -A parameterized factory, so the same options object can be reused per `id`: -```angular-ts -import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' - -export const postOptions = (id: string) => - queryOptions({ - queryKey: ['post', id], - queryFn: () => fetchPost(id), - }) - -@Component({ - selector: 'post', - template: ` - @if (postQuery.isPending()) { - Loading... - } @else if (postQuery.isError()) { - Error: {{ postQuery.error()?.message }} - } @else { -

{{ postQuery.data().title }}

- } - `, -}) -export class Post { - readonly id = signal('1') - readonly postQuery = injectQuery(() => postOptions(this.id())) -} -``` +`OmitKeyof`\<[`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>, `"queryFn"`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `TQueryFnData`, `TError`\> ## Call Signature @@ -168,11 +103,7 @@ export class Post { function queryOptions(options: UndefinedInitialDataOptions): CreateQueryOptions & object & QueryKeyWithDataTag; ``` -Defined in: [packages/angular-query-experimental/src/query-options.ts:281](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L281) - -You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options -can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is -required and is the query key to generate options for. +Defined in: [packages/angular-query/src/query-options.ts:70](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L70) ### Type Parameters @@ -198,77 +129,6 @@ required and is the query key to generate options for. [`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> -The [UndefinedInitialDataOptions](../type-aliases/UndefinedInitialDataOptions.md) to use — everything you can pass to `injectQuery`. - ### Returns -The same options object, typed so that `queryKey` carries the inferred data type. - -### See - - - [injectQuery](injectQuery.md) to run a query with these options. - - [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. - -### Remarks - -This is the only overload that accepts `queryFn: skipToken`, shown below. - -### Examples - -A parameterized factory, so the same options object can be reused per `id`: -```angular-ts -import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' - -export const postOptions = (id: string) => - queryOptions({ - queryKey: ['post', id], - queryFn: () => fetchPost(id), - }) - -@Component({ - selector: 'post', - template: ` - @if (postQuery.isPending()) { - Loading... - } @else if (postQuery.isError()) { - Error: {{ postQuery.error()?.message }} - } @else { -

{{ postQuery.data().title }}

- } - `, -}) -export class Post { - readonly id = signal('1') - readonly postQuery = injectQuery(() => postOptions(this.id())) -} -``` - -A factory that disables the query, type safe, until `postId` is set: -```angular-ts -import { queryOptions, skipToken, injectQuery } from '@tanstack/angular-query-experimental' - -export const postOptions = (postId: number | undefined) => - queryOptions({ - queryKey: ['post', postId], - queryFn: postId != null ? () => fetchPost(postId) : skipToken, - }) - -@Component({ - selector: 'post', - template: ` - @if (postId() == null) { - Select a post - } @else if (postQuery.isPending()) { - Loading... - } @else if (postQuery.isError()) { - Error: {{ postQuery.error()?.message }} - } @else { -

{{ postQuery.data().title }}

- } - `, -}) -export class Post { - readonly postId = signal(undefined) - readonly postQuery = injectQuery(() => postOptions(this.postId())) -} -``` +[`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `TQueryFnData`, `TError`\> diff --git a/docs/framework/angular/reference/functions/toResource.md b/docs/framework/angular/reference/functions/toResource.md new file mode 100644 index 00000000000..3baecfef1dd --- /dev/null +++ b/docs/framework/angular/reference/functions/toResource.md @@ -0,0 +1,34 @@ +--- +id: toResource +title: toResource +--- + +```ts +function toResource(query): QueryResource; +``` + +Defined in: [packages/angular-query/src/query-resource.ts:40](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-resource.ts#L40) + +Converts an Angular Query result into Angular's Resource interface. + +Call this function once and reuse the returned resource. + +## Type Parameters + +### TValue + +`TValue` + +## Parameters + +### query + +`QueryResourceSource`\<`TValue`\> + +An Angular Query or infinite-query result. + +## Returns + +[`QueryResource`](../interfaces/QueryResource.md)\<`TValue`\> + +A Resource-compatible view of the query result. diff --git a/docs/framework/angular/reference/functions/withHydrationKey.md b/docs/framework/angular/reference/functions/withHydrationKey.md new file mode 100644 index 00000000000..800b9158ac7 --- /dev/null +++ b/docs/framework/angular/reference/functions/withHydrationKey.md @@ -0,0 +1,35 @@ +--- +id: withHydrationKey +title: withHydrationKey +--- + +```ts +function withHydrationKey(key): QueryFeature; +``` + +Defined in: [packages/angular-query/src/providers.ts:167](https://github.com/TanStack/query/blob/main/packages/angular-query/src/providers.ts#L167) + +Sets a non-default serialization key for this injector's `QueryClient` cache (server dehydrate / +browser hydrate via `TransferState`). Use this when you have multiple `QueryClient` instances +so each has its own key. The default key applies when you do not add this feature. + +```ts +providers: [ + provideTanStackQuery( + () => new QueryClient(), + withHydrationKey('my-secondary-query-cache'), + ), +] +``` + +## Parameters + +### key + +`string` + +A unique string for this client's `TransferState` entry. + +## Returns + +[`QueryFeature`](../interfaces/QueryFeature.md) diff --git a/docs/framework/angular/reference/functions/withNoQueryHydration.md b/docs/framework/angular/reference/functions/withNoQueryHydration.md new file mode 100644 index 00000000000..b0f003789b4 --- /dev/null +++ b/docs/framework/angular/reference/functions/withNoQueryHydration.md @@ -0,0 +1,16 @@ +--- +id: withNoQueryHydration +title: withNoQueryHydration +--- + +```ts +function withNoQueryHydration(): QueryFeature; +``` + +Defined in: [packages/angular-query/src/providers.ts:181](https://github.com/TanStack/query/blob/main/packages/angular-query/src/providers.ts#L181) + +Disables `TransferState` hydration and dehydration for the current environment injector. + +## Returns + +[`QueryFeature`](../interfaces/QueryFeature.md) diff --git a/docs/framework/angular/reference/index.md b/docs/framework/angular/reference/index.md index 4b10910da24..9b511013b2c 100644 --- a/docs/framework/angular/reference/index.md +++ b/docs/framework/angular/reference/index.md @@ -1,104 +1,30 @@ --- -id: "@tanstack/angular-query-experimental" -title: "@tanstack/angular-query-experimental" +id: "@tanstack/angular-query" +title: "@tanstack/angular-query" --- -## Classes - -- [CancelledError](classes/CancelledError.md) -- [InfiniteQueryObserver](classes/InfiniteQueryObserver.md) -- [Mutation](classes/Mutation.md) -- [MutationCache](classes/MutationCache.md) -- [MutationObserver](classes/MutationObserver.md) -- [QueriesObserver](classes/QueriesObserver.md) -- [Query](classes/Query.md) -- [QueryCache](classes/QueryCache.md) -- [QueryClient](classes/QueryClient.md) -- [QueryObserver](classes/QueryObserver.md) - ## Interfaces +- [BaseInfiniteQueryNarrowing](interfaces/BaseInfiniteQueryNarrowing.md) - [BaseMutationNarrowing](interfaces/BaseMutationNarrowing.md) - [BaseQueryNarrowing](interfaces/BaseQueryNarrowing.md) -- [CancelOptions](interfaces/CancelOptions.md) -- [CreateBaseQueryOptions](interfaces/CreateBaseQueryOptions.md) - [CreateInfiniteQueryOptions](interfaces/CreateInfiniteQueryOptions.md) - [CreateMutationOptions](interfaces/CreateMutationOptions.md) -- [CreateQueryOptions](interfaces/CreateQueryOptions.md) -- [DefaultOptions](interfaces/DefaultOptions.md) -- [DehydratedState](interfaces/DehydratedState.md) -- [DehydrateOptions](interfaces/DehydrateOptions.md) -- [~~EnsureQueryDataOptions~~](interfaces/EnsureQueryDataOptions.md) -- [FetchNextPageOptions](interfaces/FetchNextPageOptions.md) -- [FetchPreviousPageOptions](interfaces/FetchPreviousPageOptions.md) -- [~~FetchQueryOptions~~](interfaces/FetchQueryOptions.md) -- [FocusManager](interfaces/FocusManager.md) -- [HydrateOptions](interfaces/HydrateOptions.md) -- [InfiniteData](interfaces/InfiniteData.md) -- [InfiniteQueryObserverBaseResult](interfaces/InfiniteQueryObserverBaseResult.md) -- [InfiniteQueryObserverLoadingErrorResult](interfaces/InfiniteQueryObserverLoadingErrorResult.md) -- [InfiniteQueryObserverLoadingResult](interfaces/InfiniteQueryObserverLoadingResult.md) -- [InfiniteQueryObserverOptions](interfaces/InfiniteQueryObserverOptions.md) -- [InfiniteQueryObserverPendingResult](interfaces/InfiniteQueryObserverPendingResult.md) -- [InfiniteQueryObserverPlaceholderResult](interfaces/InfiniteQueryObserverPlaceholderResult.md) -- [InfiniteQueryObserverRefetchErrorResult](interfaces/InfiniteQueryObserverRefetchErrorResult.md) -- [InfiniteQueryObserverSuccessResult](interfaces/InfiniteQueryObserverSuccessResult.md) -- [InfiniteQueryPageParamsOptions](interfaces/InfiniteQueryPageParamsOptions.md) -- [InitialPageParam](interfaces/InitialPageParam.md) -- [InjectInfiniteQueryOptions](interfaces/InjectInfiniteQueryOptions.md) -- [InjectIsFetchingOptions](interfaces/InjectIsFetchingOptions.md) -- [InjectIsMutatingOptions](interfaces/InjectIsMutatingOptions.md) -- [InjectMutationOptions](interfaces/InjectMutationOptions.md) -- [InjectMutationStateOptions](interfaces/InjectMutationStateOptions.md) -- [InjectQueryOptions](interfaces/InjectQueryOptions.md) -- [InvalidateOptions](interfaces/InvalidateOptions.md) -- [InvalidateQueryFilters](interfaces/InvalidateQueryFilters.md) -- [MutateOptions](interfaces/MutateOptions.md) -- [MutationCacheConfig](interfaces/MutationCacheConfig.md) -- [MutationFilters](interfaces/MutationFilters.md) -- [MutationObserverBaseResult](interfaces/MutationObserverBaseResult.md) -- [MutationObserverErrorResult](interfaces/MutationObserverErrorResult.md) -- [MutationObserverIdleResult](interfaces/MutationObserverIdleResult.md) -- [MutationObserverLoadingResult](interfaces/MutationObserverLoadingResult.md) -- [MutationObserverOptions](interfaces/MutationObserverOptions.md) -- [MutationObserverSuccessResult](interfaces/MutationObserverSuccessResult.md) -- [MutationOptions](interfaces/MutationOptions.md) -- [MutationState](interfaces/MutationState.md) -- [NotifyEvent](interfaces/NotifyEvent.md) -- [OnlineManager](interfaces/OnlineManager.md) -- [QueriesObserverOptions](interfaces/QueriesObserverOptions.md) -- [QueryCacheConfig](interfaces/QueryCacheConfig.md) -- [QueryClientConfig](interfaces/QueryClientConfig.md) -- [QueryExecuteOptions](interfaces/QueryExecuteOptions.md) +- [DefinedInfiniteQueryNarrowing](interfaces/DefinedInfiniteQueryNarrowing.md) +- [DefinedQueryNarrowing](interfaces/DefinedQueryNarrowing.md) +- [InjectQueriesOptions](interfaces/InjectQueriesOptions.md) - [QueryFeature](interfaces/QueryFeature.md) -- [QueryFilters](interfaces/QueryFilters.md) -- [QueryObserverBaseResult](interfaces/QueryObserverBaseResult.md) -- [QueryObserverLoadingErrorResult](interfaces/QueryObserverLoadingErrorResult.md) -- [QueryObserverLoadingResult](interfaces/QueryObserverLoadingResult.md) -- [QueryObserverOptions](interfaces/QueryObserverOptions.md) -- [QueryObserverPendingResult](interfaces/QueryObserverPendingResult.md) -- [QueryObserverPlaceholderResult](interfaces/QueryObserverPlaceholderResult.md) -- [QueryObserverRefetchErrorResult](interfaces/QueryObserverRefetchErrorResult.md) -- [QueryObserverSuccessResult](interfaces/QueryObserverSuccessResult.md) -- [QueryOptions](interfaces/QueryOptions.md) -- [QueryState](interfaces/QueryState.md) -- [RefetchOptions](interfaces/RefetchOptions.md) -- [RefetchQueryFilters](interfaces/RefetchQueryFilters.md) -- [Register](interfaces/Register.md) -- [ResetOptions](interfaces/ResetOptions.md) -- [ResultOptions](interfaces/ResultOptions.md) -- [SetDataOptions](interfaces/SetDataOptions.md) -- [TimeoutManager](interfaces/TimeoutManager.md) +- [QueryResource](interfaces/QueryResource.md) ## Type Aliases -- [AnyDataTag](type-aliases/AnyDataTag.md) - [CreateBaseMutationResult](type-aliases/CreateBaseMutationResult.md) - [CreateBaseQueryResult](type-aliases/CreateBaseQueryResult.md) - [CreateInfiniteQueryResult](type-aliases/CreateInfiniteQueryResult.md) - [CreateMutateAsyncFunction](type-aliases/CreateMutateAsyncFunction.md) - [CreateMutateFunction](type-aliases/CreateMutateFunction.md) - [CreateMutationResult](type-aliases/CreateMutationResult.md) +- [CreateQueryOptions](type-aliases/CreateQueryOptions.md) - [CreateQueryResult](type-aliases/CreateQueryResult.md) - [DataTag](type-aliases/DataTag.md) - [dataTagErrorSymbol](type-aliases/dataTagErrorSymbol.md) @@ -111,59 +37,10 @@ title: "@tanstack/angular-query-experimental" - [DefinedInfiniteQueryObserverResult](type-aliases/DefinedInfiniteQueryObserverResult.md) - [DefinedInitialDataInfiniteOptions](type-aliases/DefinedInitialDataInfiniteOptions.md) - [DefinedInitialDataOptions](type-aliases/DefinedInitialDataOptions.md) -- [DefinedQueryObserverResult](type-aliases/DefinedQueryObserverResult.md) -- [DevtoolsFeature](type-aliases/DevtoolsFeature.md) -- [DistributiveOmit](type-aliases/DistributiveOmit.md) -- [~~EnsureInfiniteQueryDataOptions~~](type-aliases/EnsureInfiniteQueryDataOptions.md) -- [~~FetchInfiniteQueryOptions~~](type-aliases/FetchInfiniteQueryOptions.md) -- [FetchStatus](type-aliases/FetchStatus.md) -- [GetNextPageParamFunction](type-aliases/GetNextPageParamFunction.md) -- [GetPreviousPageParamFunction](type-aliases/GetPreviousPageParamFunction.md) -- [InferDataFromTag](type-aliases/InferDataFromTag.md) -- [InferErrorFromTag](type-aliases/InferErrorFromTag.md) -- [InfiniteQueryExecuteOptions](type-aliases/InfiniteQueryExecuteOptions.md) -- [InfiniteQueryObserverResult](type-aliases/InfiniteQueryObserverResult.md) -- [InitialDataFunction](type-aliases/InitialDataFunction.md) -- [ManagedTimerId](type-aliases/ManagedTimerId.md) -- [MutateFunction](type-aliases/MutateFunction.md) -- [MutateFunctionRest](type-aliases/MutateFunctionRest.md) -- [MutationCacheNotifyEvent](type-aliases/MutationCacheNotifyEvent.md) -- [MutationFunction](type-aliases/MutationFunction.md) -- [MutationFunctionContext](type-aliases/MutationFunctionContext.md) -- [MutationKey](type-aliases/MutationKey.md) -- [MutationMeta](type-aliases/MutationMeta.md) -- [MutationObserverResult](type-aliases/MutationObserverResult.md) -- [MutationScope](type-aliases/MutationScope.md) -- [MutationStatus](type-aliases/MutationStatus.md) -- [NetworkMode](type-aliases/NetworkMode.md) -- [NonUndefinedGuard](type-aliases/NonUndefinedGuard.md) -- [NotifyEventType](type-aliases/NotifyEventType.md) -- [NotifyOnChangeProps](type-aliases/NotifyOnChangeProps.md) -- [OmitKeyof](type-aliases/OmitKeyof.md) -- [Override](type-aliases/Override.md) -- [PersistQueryClientFeature](type-aliases/PersistQueryClientFeature.md) -- [PlaceholderDataFunction](type-aliases/PlaceholderDataFunction.md) +- [MutationStateOptions](type-aliases/MutationStateOptions.md) - [QueriesOptions](type-aliases/QueriesOptions.md) - [QueriesPlaceholderDataFunction](type-aliases/QueriesPlaceholderDataFunction.md) - [QueriesResults](type-aliases/QueriesResults.md) -- [QueryBooleanOption](type-aliases/QueryBooleanOption.md) -- [QueryCacheNotifyEvent](type-aliases/QueryCacheNotifyEvent.md) -- [QueryFeatures](type-aliases/QueryFeatures.md) -- [QueryFunction](type-aliases/QueryFunction.md) -- [QueryFunctionContext](type-aliases/QueryFunctionContext.md) -- [QueryKey](type-aliases/QueryKey.md) -- [QueryKeyHashFunction](type-aliases/QueryKeyHashFunction.md) -- [QueryKeyWithDataTag](type-aliases/QueryKeyWithDataTag.md) -- [QueryMeta](type-aliases/QueryMeta.md) -- [QueryObserverResult](type-aliases/QueryObserverResult.md) -- [QueryPersister](type-aliases/QueryPersister.md) -- [QueryStatus](type-aliases/QueryStatus.md) -- [SkipToken](type-aliases/SkipToken.md) -- [StaleTime](type-aliases/StaleTime.md) -- [StaleTimeFunction](type-aliases/StaleTimeFunction.md) -- [ThrowOnError](type-aliases/ThrowOnError.md) -- [TimeoutCallback](type-aliases/TimeoutCallback.md) -- [TimeoutProvider](type-aliases/TimeoutProvider.md) - [UndefinedInitialDataInfiniteOptions](type-aliases/UndefinedInitialDataInfiniteOptions.md) - [UndefinedInitialDataOptions](type-aliases/UndefinedInitialDataOptions.md) - [UnsetMarker](type-aliases/UnsetMarker.md) @@ -202,20 +79,11 @@ title: "@tanstack/angular-query-experimental" - [injectIsRestoring](functions/injectIsRestoring.md) - [injectMutation](functions/injectMutation.md) - [injectMutationState](functions/injectMutationState.md) +- [injectQueries](functions/injectQueries.md) - [injectQuery](functions/injectQuery.md) -- [~~injectQueryClient~~](functions/injectQueryClient.md) -- [~~isCancelledError~~](functions/isCancelledError.md) -- [keepPreviousData](functions/keepPreviousData.md) -- [matchMutation](functions/matchMutation.md) -- [matchQuery](functions/matchQuery.md) - [mutationOptions](functions/mutationOptions.md) -- [noop](functions/noop.md) -- [partialMatchKey](functions/partialMatchKey.md) -- [~~provideAngularQuery~~](functions/provideAngularQuery.md) -- [provideIsRestoring](functions/provideIsRestoring.md) -- [provideQueryClient](functions/provideQueryClient.md) - [provideTanStackQuery](functions/provideTanStackQuery.md) -- [queryFeature](functions/queryFeature.md) - [queryOptions](functions/queryOptions.md) -- [replaceEqualDeep](functions/replaceEqualDeep.md) -- [shouldThrowError](functions/shouldThrowError.md) +- [toResource](functions/toResource.md) +- [withHydrationKey](functions/withHydrationKey.md) +- [withNoQueryHydration](functions/withNoQueryHydration.md) diff --git a/docs/framework/angular/reference/interfaces/BaseInfiniteQueryNarrowing.md b/docs/framework/angular/reference/interfaces/BaseInfiniteQueryNarrowing.md new file mode 100644 index 00000000000..252eb9e27b8 --- /dev/null +++ b/docs/framework/angular/reference/interfaces/BaseInfiniteQueryNarrowing.md @@ -0,0 +1,46 @@ +--- +id: BaseInfiniteQueryNarrowing +title: BaseInfiniteQueryNarrowing +--- + +Defined in: [packages/angular-query/src/types.ts:114](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L114) + +## Type Parameters + +### TData + +`TData` = `unknown` + +### TError + +`TError` = `DefaultError` + +## Properties + +### isError + +```ts +isError: SignalFunction<(this) => this is CreateInfiniteQueryResult>>; +``` + +Defined in: [packages/angular-query/src/types.ts:127](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L127) + +*** + +### isPending + +```ts +isPending: SignalFunction<(this) => this is CreateInfiniteQueryResult>>; +``` + +Defined in: [packages/angular-query/src/types.ts:136](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L136) + +*** + +### isSuccess + +```ts +isSuccess: SignalFunction<(this) => this is CreateInfiniteQueryResult>>; +``` + +Defined in: [packages/angular-query/src/types.ts:118](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L118) diff --git a/docs/framework/angular/reference/interfaces/BaseMutationNarrowing.md b/docs/framework/angular/reference/interfaces/BaseMutationNarrowing.md index c3f71f3a8cf..af8dfb3884d 100644 --- a/docs/framework/angular/reference/interfaces/BaseMutationNarrowing.md +++ b/docs/framework/angular/reference/interfaces/BaseMutationNarrowing.md @@ -3,11 +3,7 @@ id: BaseMutationNarrowing title: BaseMutationNarrowing --- -Defined in: [packages/angular-query-experimental/src/types.ts:328](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L328) - -The `isSuccess`/`isError`/`isPending`/`isIdle` methods on a mutation result. Each is both a `Signal` -(its current boolean value is read reactively without calling it) and a type-guard function you can -call — `if (mutation.isSuccess())` — so that `mutation.data` narrows away `undefined` inside the branch. +Defined in: [packages/angular-query/src/types.ts:297](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L297) ## Type Parameters @@ -38,9 +34,40 @@ their `onMutateResult` parameter — useful for optimistic-update rollback data. ## Properties -| Property | Type | -| ------ | ------ | -| `isError` | `SignalFunction`\<(`this`: [`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>) => `this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>`\> | -| `isIdle` | `SignalFunction`\<(`this`: [`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>) => `this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>`\> | -| `isPending` | `SignalFunction`\<(`this`: [`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>) => `this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>`\> | -| `isSuccess` | `SignalFunction`\<(`this`: [`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>) => `this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>`\> | +### isError + +```ts +isError: SignalFunction<(this) => this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>>; +``` + +Defined in: [packages/angular-query/src/types.ts:320](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L320) + +*** + +### isIdle + +```ts +isIdle: SignalFunction<(this) => this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>>; +``` + +Defined in: [packages/angular-query/src/types.ts:354](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L354) + +*** + +### isPending + +```ts +isPending: SignalFunction<(this) => this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>>; +``` + +Defined in: [packages/angular-query/src/types.ts:337](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L337) + +*** + +### isSuccess + +```ts +isSuccess: SignalFunction<(this) => this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>>; +``` + +Defined in: [packages/angular-query/src/types.ts:303](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L303) diff --git a/docs/framework/angular/reference/interfaces/BaseQueryNarrowing.md b/docs/framework/angular/reference/interfaces/BaseQueryNarrowing.md index 44bb504262e..38ffb777ec0 100644 --- a/docs/framework/angular/reference/interfaces/BaseQueryNarrowing.md +++ b/docs/framework/angular/reference/interfaces/BaseQueryNarrowing.md @@ -3,12 +3,7 @@ id: BaseQueryNarrowing title: BaseQueryNarrowing --- -Defined in: [packages/angular-query-experimental/src/types.ts:83](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L83) - -The `isSuccess`/`isError`/`isPending` methods on a query result. Unlike `react-query`'s derived booleans, -these are type-guard methods you call — `if (query.isSuccess())` — so that `query.data` narrows away -`undefined` inside the branch, the same way `status` narrowing works on the plain object `react-query` -returns. +Defined in: [packages/angular-query/src/types.ts:60](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L60) ## Type Parameters @@ -26,8 +21,30 @@ The type of errors your `queryFn` may throw. ## Properties -| Property | Type | -| ------ | ------ | -| `isError` | (`this`: [`CreateBaseQueryResult`](../type-aliases/CreateBaseQueryResult.md)\<`TData`, `TError`\>) => `this is CreateBaseQueryResult>` | -| `isPending` | (`this`: [`CreateBaseQueryResult`](../type-aliases/CreateBaseQueryResult.md)\<`TData`, `TError`\>) => `this is CreateBaseQueryResult>` | -| `isSuccess` | (`this`: [`CreateBaseQueryResult`](../type-aliases/CreateBaseQueryResult.md)\<`TData`, `TError`\>) => `this is CreateBaseQueryResult>` | +### isError + +```ts +isError: SignalFunction<(this) => this is CreateBaseQueryResult>>; +``` + +Defined in: [packages/angular-query/src/types.ts:70](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L70) + +*** + +### isPending + +```ts +isPending: SignalFunction<(this) => this is CreateBaseQueryResult>>; +``` + +Defined in: [packages/angular-query/src/types.ts:79](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L79) + +*** + +### isSuccess + +```ts +isSuccess: SignalFunction<(this) => this is CreateBaseQueryResult>>; +``` + +Defined in: [packages/angular-query/src/types.ts:61](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L61) diff --git a/docs/framework/angular/reference/interfaces/CreateBaseQueryOptions.md b/docs/framework/angular/reference/interfaces/CreateBaseQueryOptions.md deleted file mode 100644 index f19f5b53089..00000000000 --- a/docs/framework/angular/reference/interfaces/CreateBaseQueryOptions.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: CreateBaseQueryOptions -title: CreateBaseQueryOptions ---- - -Defined in: [packages/angular-query-experimental/src/types.ts:34](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L34) - -The options shared across `angular-query-experimental`'s query functions. Extends -[QueryObserverOptions](QueryObserverOptions.md) from `@tanstack/query-core` as-is — unlike `react-query`, -`angular-query-experimental` has no extra framework-specific option here. - -## Extends - -- [`QueryObserverOptions`](QueryObserverOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryData`, `TQueryKey`\> - -## Type Parameters - -### TQueryFnData - -`TQueryFnData` = `unknown` - -The type your `queryFn` resolves to. - -### TError - -`TError` = [`DefaultError`](../type-aliases/DefaultError.md) - -The type of errors your `queryFn` may throw. - -### TData - -`TData` = `TQueryFnData` - -The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no -`select` is used. - -### TQueryData - -`TQueryData` = `TQueryFnData` - -The type of the data actually held in the query cache — the input to `select` and -`placeholderData`. Defaults to, and is usually the same as, `TQueryFnData`. - -### TQueryKey - -`TQueryKey` *extends* [`QueryKey`](../type-aliases/QueryKey.md) = [`QueryKey`](../type-aliases/QueryKey.md) - -The type of your `queryKey`. - -## Properties - -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `enabled?` | \| `false` \| `true` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` | `true` | Set this to `false` or a function that returns `false` to disable automatic refetching when the query mounts or changes query keys. To refetch the query, use the `refetch` method returned from the `useQuery` instance. Accepts a boolean or function that returns a boolean. | -| `gcTime?` | `number` | `undefined` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | -| `initialData?` | `TQueryData` \| () => `TQueryData` \| `undefined` | `undefined` | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | -| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | -| `maxPages?` | `number` | `undefined` | Maximum number of pages to store in the data of an infinite query. | -| `meta?` | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | -| `networkMode?` | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a query is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| `notifyOnChangeProps?` | \| ( \| `"error"` \| `"data"` \| `"isError"` \| `"isPending"` \| `"isLoading"` \| `"isLoadingError"` \| `"isRefetchError"` \| `"isSuccess"` \| `"isPlaceholderData"` \| `"status"` \| `"dataUpdatedAt"` \| `"errorUpdatedAt"` \| `"failureCount"` \| `"failureReason"` \| `"errorUpdateCount"` \| `"isFetched"` \| `"isFetchedAfterMount"` \| `"isFetching"` \| `"isInitialLoading"` \| `"isPaused"` \| `"isRefetching"` \| `"isStale"` \| `"isEnabled"` \| `"refetch"` \| `"fetchStatus"` \| `"fetchNextPage"` \| `"fetchPreviousPage"` \| `"hasNextPage"` \| `"hasPreviousPage"` \| `"isFetchNextPageError"` \| `"isFetchingNextPage"` \| `"isFetchPreviousPageError"` \| `"isFetchingPreviousPage"`)[] \| `"all"` \| () => \| `"all"` \| ( \| `"error"` \| `"data"` \| `"isError"` \| `"isPending"` \| `"isLoading"` \| `"isLoadingError"` \| `"isRefetchError"` \| `"isSuccess"` \| `"isPlaceholderData"` \| `"status"` \| `"dataUpdatedAt"` \| `"errorUpdatedAt"` \| `"failureCount"` \| `"failureReason"` \| `"errorUpdateCount"` \| `"isFetched"` \| `"isFetchedAfterMount"` \| `"isFetching"` \| `"isInitialLoading"` \| `"isPaused"` \| `"isRefetching"` \| `"isStale"` \| `"isEnabled"` \| `"refetch"` \| `"fetchStatus"` \| `"fetchNextPage"` \| `"fetchPreviousPage"` \| `"hasNextPage"` \| `"hasPreviousPage"` \| `"isFetchNextPageError"` \| `"isFetchingNextPage"` \| `"isFetchPreviousPageError"` \| `"isFetchingPreviousPage"`)[] \| `undefined` | `undefined` | If set, the component will only re-render if any of the listed properties change. When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change. When set to `'all'`, the component will re-render whenever a query is updated. When set to a function, the function will be executed to compute the list of properties. Defaults to `undefined`, in which case property access is tracked automatically, and the component only re-renders when one of the tracked properties changes. | -| `persister?` | (`queryFn`: (`context`: `object`) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\>, `context`: `object`, `query`: [`Query`](../classes/Query.md)) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | -| `placeholderData?` | \| `NonFunctionGuard`\<`TQueryData`\> \| (`previousData`: `NonFunctionGuard`\<`TQueryData`\> \| `undefined`, `previousQuery`: \| [`Query`](../classes/Query.md)\<`NonFunctionGuard`\<`TQueryData`\>, `TError`, `NonFunctionGuard`\<`TQueryData`\>, `TQueryKey`\> \| `undefined`) => `NonFunctionGuard`\<`TQueryData`\> \| `undefined` | `undefined` | If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `loading` data and no initialData has been provided. | -| `queryFn?` | \| *typeof* [`skipToken`](../variables/skipToken.md) \| (`context`: `object`) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | -| `queryHash?` | `string` | `undefined` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | -| `queryKey` | `TQueryKey` & `object` | `undefined` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | -| `queryKeyHashFn?` | (`queryKey`: `TQueryKey`) => `string` | `undefined` | If specified, this function is used to hash the `queryKey` to a string. | -| `refetchInterval?` | \| `number` \| `false` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `number` \| `false` \| `undefined` | `false` | If set to a number, the query will continuously refetch at this frequency in milliseconds. If set to a function, the function will be executed with the latest data and query to compute a frequency | -| `refetchIntervalInBackground?` | `boolean` | `false` | If set to `true`, the query will continue to refetch while their tab/window is in the background. | -| `refetchOnMount?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` \| `"always"` | `true` | If set to `true`, the query will refetch on mount if the data is stale. If set to `false`, will disable additional instances of a query to trigger background refetch. If set to `'always'`, the query will always refetch on mount (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value | -| `refetchOnReconnect?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` \| `"always"` | `undefined` | If set to `true`, the query will refetch on reconnect if the data is stale. If set to `false`, the query will not refetch on reconnect. If set to `'always'`, the query will always refetch on reconnect (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. Defaults to `true` unless `networkMode` is `'always'`. | -| `refetchOnWindowFocus?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` \| `"always"` | `true` | If set to `true`, the query will refetch on window focus if the data is stale. If set to `false`, the query will not refetch on window focus. If set to `'always'`, the query will always refetch on window focus (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. | -| `retry?` | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `undefined` | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | -| `retryDelay?` | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| `retryOnMount?` | \| `false` \| `true` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` | `true` | If set to `false`, the query will not be retried on mount if it contains an error. If set to a function, the function will be executed with the query to compute the value. | -| `select?` | (`data`: `TQueryData`) => `TData` | `undefined` | This option can be used to transform or select a part of the data returned by the query function. It affects the returned `data` value, but does not affect what gets stored in the query cache. The `select` function will only run if `data` changed, or if the reference to the `select` function itself changes. To optimize, memoize the function so its reference stays stable across calls. | -| `staleTime?` | \| `number` \| `"static"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `number` \| `"static"` | `0` | The time in milliseconds after data is considered stale. If set to `Infinity`, the data will never be considered stale. If set to `'static'`, the data will never be considered stale. If set to a function, the function will be executed with the query to compute a `staleTime`. | -| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | `true` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. | -| `suspense?` | `boolean` | `false` | If set to `true`, the query will suspend when `status === 'pending'` and throw errors when `status === 'error'`. | -| `throwOnError?` | \| `false` \| `true` \| (`error`: `TError`, `query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` | `false` | Whether errors should be thrown instead of setting the `error` property. If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary. If set to `false` and `suspense` is `false`, errors are returned as state. If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`). | diff --git a/docs/framework/angular/reference/interfaces/CreateInfiniteQueryOptions.md b/docs/framework/angular/reference/interfaces/CreateInfiniteQueryOptions.md index e4c7351f412..119ea6792d0 100644 --- a/docs/framework/angular/reference/interfaces/CreateInfiniteQueryOptions.md +++ b/docs/framework/angular/reference/interfaces/CreateInfiniteQueryOptions.md @@ -3,16 +3,11 @@ id: CreateInfiniteQueryOptions title: CreateInfiniteQueryOptions --- -Defined in: [packages/angular-query-experimental/src/types.ts:121](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L121) - -The options accepted by `injectInfiniteQuery`. Same as [CreateBaseQueryOptions](CreateBaseQueryOptions.md), minus `suspense` — -which `angular-query-experimental` doesn't support, unlike `react-query` — extends -[InfiniteQueryObserverOptions](InfiniteQueryObserverOptions.md) from `@tanstack/query-core` for the infinite-query-specific options -(`getNextPageParam`, `initialPageParam`, etc.). +Defined in: [packages/angular-query/src/types.ts:174](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L174) ## Extends -- [`OmitKeyof`](../type-aliases/OmitKeyof.md)\<[`InfiniteQueryObserverOptions`](InfiniteQueryObserverOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>, `"suspense"`\> +- `OmitKeyof`\<`InfiniteQueryObserverOptions`\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>, `"notifyOnChangeProps"` \| `"suspense"` \| `"throwOnError"`\> ## Type Parameters diff --git a/docs/framework/angular/reference/interfaces/CreateMutationOptions.md b/docs/framework/angular/reference/interfaces/CreateMutationOptions.md index 6136d4494e8..ca80deb6903 100644 --- a/docs/framework/angular/reference/interfaces/CreateMutationOptions.md +++ b/docs/framework/angular/reference/interfaces/CreateMutationOptions.md @@ -3,14 +3,11 @@ id: CreateMutationOptions title: CreateMutationOptions --- -Defined in: [packages/angular-query-experimental/src/types.ts:224](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L224) - -The options accepted by `injectMutation`. Same as [MutationObserverOptions](MutationObserverOptions.md) from -`@tanstack/query-core`, minus the internal `_defaulted` flag. +Defined in: [packages/angular-query/src/types.ts:241](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L241) ## Extends -- [`OmitKeyof`](../type-aliases/OmitKeyof.md)\<[`MutationObserverOptions`](MutationObserverOptions.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>, `"_defaulted"`\> +- `OmitKeyof`\<`MutationObserverOptions`\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>, `"_defaulted"` \| `"throwOnError"`\> ## Type Parameters diff --git a/docs/framework/angular/reference/interfaces/CreateQueryOptions.md b/docs/framework/angular/reference/interfaces/CreateQueryOptions.md deleted file mode 100644 index ff07a5c9125..00000000000 --- a/docs/framework/angular/reference/interfaces/CreateQueryOptions.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -id: CreateQueryOptions -title: CreateQueryOptions ---- - -Defined in: [packages/angular-query-experimental/src/types.ts:58](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L58) - -The options accepted by `injectQuery`. Same as [CreateBaseQueryOptions](CreateBaseQueryOptions.md), minus `suspense` — which -`angular-query-experimental` doesn't support, unlike `react-query`. - -## Extends - -- [`OmitKeyof`](../type-aliases/OmitKeyof.md)\<[`CreateBaseQueryOptions`](CreateBaseQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryFnData`, `TQueryKey`\>, `"suspense"`\> - -## Type Parameters - -### TQueryFnData - -`TQueryFnData` = `unknown` - -The type your `queryFn` resolves to. - -### TError - -`TError` = [`DefaultError`](../type-aliases/DefaultError.md) - -The type of errors your `queryFn` may throw. - -### TData - -`TData` = `TQueryFnData` - -The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no -`select` is used. - -### TQueryKey - -`TQueryKey` *extends* [`QueryKey`](../type-aliases/QueryKey.md) = [`QueryKey`](../type-aliases/QueryKey.md) - -The type of your `queryKey`. - -## Properties - -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `enabled?` | \| `false` \| `true` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryFnData`, `TQueryKey`\>) => `boolean` | `true` | Set this to `false` or a function that returns `false` to disable automatic refetching when the query mounts or changes query keys. To refetch the query, use the `refetch` method returned from the `useQuery` instance. Accepts a boolean or function that returns a boolean. | -| `gcTime?` | `number` | `undefined` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | -| `initialData?` | `TQueryFnData` \| () => `TQueryFnData` \| `undefined` | `undefined` | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | -| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | -| `maxPages?` | `number` | `undefined` | Maximum number of pages to store in the data of an infinite query. | -| `meta?` | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | -| `networkMode?` | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a query is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| `notifyOnChangeProps?` | \| ( \| `"error"` \| `"data"` \| `"isError"` \| `"isPending"` \| `"isLoading"` \| `"isLoadingError"` \| `"isRefetchError"` \| `"isSuccess"` \| `"isPlaceholderData"` \| `"status"` \| `"dataUpdatedAt"` \| `"errorUpdatedAt"` \| `"failureCount"` \| `"failureReason"` \| `"errorUpdateCount"` \| `"isFetched"` \| `"isFetchedAfterMount"` \| `"isFetching"` \| `"isInitialLoading"` \| `"isPaused"` \| `"isRefetching"` \| `"isStale"` \| `"isEnabled"` \| `"refetch"` \| `"fetchStatus"` \| `"fetchNextPage"` \| `"fetchPreviousPage"` \| `"hasNextPage"` \| `"hasPreviousPage"` \| `"isFetchNextPageError"` \| `"isFetchingNextPage"` \| `"isFetchPreviousPageError"` \| `"isFetchingPreviousPage"`)[] \| `"all"` \| () => \| `"all"` \| ( \| `"error"` \| `"data"` \| `"isError"` \| `"isPending"` \| `"isLoading"` \| `"isLoadingError"` \| `"isRefetchError"` \| `"isSuccess"` \| `"isPlaceholderData"` \| `"status"` \| `"dataUpdatedAt"` \| `"errorUpdatedAt"` \| `"failureCount"` \| `"failureReason"` \| `"errorUpdateCount"` \| `"isFetched"` \| `"isFetchedAfterMount"` \| `"isFetching"` \| `"isInitialLoading"` \| `"isPaused"` \| `"isRefetching"` \| `"isStale"` \| `"isEnabled"` \| `"refetch"` \| `"fetchStatus"` \| `"fetchNextPage"` \| `"fetchPreviousPage"` \| `"hasNextPage"` \| `"hasPreviousPage"` \| `"isFetchNextPageError"` \| `"isFetchingNextPage"` \| `"isFetchPreviousPageError"` \| `"isFetchingPreviousPage"`)[] \| `undefined` | `undefined` | If set, the component will only re-render if any of the listed properties change. When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change. When set to `'all'`, the component will re-render whenever a query is updated. When set to a function, the function will be executed to compute the list of properties. Defaults to `undefined`, in which case property access is tracked automatically, and the component only re-renders when one of the tracked properties changes. | -| `persister?` | (`queryFn`: (`context`: `object`) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\>, `context`: `object`, `query`: [`Query`](../classes/Query.md)) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | -| `placeholderData?` | \| `NonFunctionGuard`\<`TQueryFnData`\> \| (`previousData`: `NonFunctionGuard`\<`TQueryFnData`\> \| `undefined`, `previousQuery`: \| [`Query`](../classes/Query.md)\<`NonFunctionGuard`\<`TQueryFnData`\>, `TError`, `NonFunctionGuard`\<`TQueryFnData`\>, `TQueryKey`\> \| `undefined`) => `NonFunctionGuard`\<`TQueryFnData`\> \| `undefined` | `undefined` | If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `loading` data and no initialData has been provided. | -| `queryFn?` | \| *typeof* [`skipToken`](../variables/skipToken.md) \| (`context`: `object`) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | -| `queryHash?` | `string` | `undefined` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | -| `queryKey` | `TQueryKey` & `object` | `undefined` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | -| `queryKeyHashFn?` | (`queryKey`: `TQueryKey`) => `string` | `undefined` | If specified, this function is used to hash the `queryKey` to a string. | -| `refetchInterval?` | \| `number` \| `false` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryFnData`, `TQueryKey`\>) => `number` \| `false` \| `undefined` | `false` | If set to a number, the query will continuously refetch at this frequency in milliseconds. If set to a function, the function will be executed with the latest data and query to compute a frequency | -| `refetchIntervalInBackground?` | `boolean` | `false` | If set to `true`, the query will continue to refetch while their tab/window is in the background. | -| `refetchOnMount?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryFnData`, `TQueryKey`\>) => `boolean` \| `"always"` | `true` | If set to `true`, the query will refetch on mount if the data is stale. If set to `false`, will disable additional instances of a query to trigger background refetch. If set to `'always'`, the query will always refetch on mount (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value | -| `refetchOnReconnect?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryFnData`, `TQueryKey`\>) => `boolean` \| `"always"` | `undefined` | If set to `true`, the query will refetch on reconnect if the data is stale. If set to `false`, the query will not refetch on reconnect. If set to `'always'`, the query will always refetch on reconnect (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. Defaults to `true` unless `networkMode` is `'always'`. | -| `refetchOnWindowFocus?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryFnData`, `TQueryKey`\>) => `boolean` \| `"always"` | `true` | If set to `true`, the query will refetch on window focus if the data is stale. If set to `false`, the query will not refetch on window focus. If set to `'always'`, the query will always refetch on window focus (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. | -| `retry?` | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `undefined` | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | -| `retryDelay?` | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| `retryOnMount?` | \| `false` \| `true` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryFnData`, `TQueryKey`\>) => `boolean` | `true` | If set to `false`, the query will not be retried on mount if it contains an error. If set to a function, the function will be executed with the query to compute the value. | -| `select?` | (`data`: `TQueryFnData`) => `TData` | `undefined` | This option can be used to transform or select a part of the data returned by the query function. It affects the returned `data` value, but does not affect what gets stored in the query cache. The `select` function will only run if `data` changed, or if the reference to the `select` function itself changes. To optimize, memoize the function so its reference stays stable across calls. | -| `staleTime?` | \| `number` \| `"static"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryFnData`, `TQueryKey`\>) => `number` \| `"static"` | `0` | The time in milliseconds after data is considered stale. If set to `Infinity`, the data will never be considered stale. If set to `'static'`, the data will never be considered stale. If set to a function, the function will be executed with the query to compute a `staleTime`. | -| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | `true` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. | -| `throwOnError?` | \| `false` \| `true` \| (`error`: `TError`, `query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryFnData`, `TQueryKey`\>) => `boolean` | `false` | Whether errors should be thrown instead of setting the `error` property. If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary. If set to `false` and `suspense` is `false`, errors are returned as state. If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`). | diff --git a/docs/framework/angular/reference/interfaces/DefinedInfiniteQueryNarrowing.md b/docs/framework/angular/reference/interfaces/DefinedInfiniteQueryNarrowing.md new file mode 100644 index 00000000000..a2057b81868 --- /dev/null +++ b/docs/framework/angular/reference/interfaces/DefinedInfiniteQueryNarrowing.md @@ -0,0 +1,46 @@ +--- +id: DefinedInfiniteQueryNarrowing +title: DefinedInfiniteQueryNarrowing +--- + +Defined in: [packages/angular-query/src/types.ts:147](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L147) + +## Type Parameters + +### TData + +`TData` = `unknown` + +### TError + +`TError` = `DefaultError` + +## Properties + +### isError + +```ts +isError: SignalFunction<(this) => this is DefinedCreateInfiniteQueryResult>>; +``` + +Defined in: [packages/angular-query/src/types.ts:160](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L160) + +*** + +### isPending + +```ts +isPending: SignalFunction<(this) => this is never>; +``` + +Defined in: [packages/angular-query/src/types.ts:169](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L169) + +*** + +### isSuccess + +```ts +isSuccess: SignalFunction<(this) => this is DefinedCreateInfiniteQueryResult>>; +``` + +Defined in: [packages/angular-query/src/types.ts:151](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L151) diff --git a/docs/framework/angular/reference/interfaces/DefinedQueryNarrowing.md b/docs/framework/angular/reference/interfaces/DefinedQueryNarrowing.md new file mode 100644 index 00000000000..ee6773e5df2 --- /dev/null +++ b/docs/framework/angular/reference/interfaces/DefinedQueryNarrowing.md @@ -0,0 +1,46 @@ +--- +id: DefinedQueryNarrowing +title: DefinedQueryNarrowing +--- + +Defined in: [packages/angular-query/src/types.ts:90](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L90) + +## Type Parameters + +### TData + +`TData` = `unknown` + +### TError + +`TError` = `DefaultError` + +## Properties + +### isError + +```ts +isError: SignalFunction<(this) => this is DefinedCreateQueryResult>>; +``` + +Defined in: [packages/angular-query/src/types.ts:100](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L100) + +*** + +### isPending + +```ts +isPending: SignalFunction<(this) => this is never>; +``` + +Defined in: [packages/angular-query/src/types.ts:109](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L109) + +*** + +### isSuccess + +```ts +isSuccess: SignalFunction<(this) => this is DefinedCreateQueryResult>>; +``` + +Defined in: [packages/angular-query/src/types.ts:91](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L91) diff --git a/docs/framework/angular/reference/interfaces/InjectInfiniteQueryOptions.md b/docs/framework/angular/reference/interfaces/InjectInfiniteQueryOptions.md deleted file mode 100644 index d4db0ff3801..00000000000 --- a/docs/framework/angular/reference/interfaces/InjectInfiniteQueryOptions.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: InjectInfiniteQueryOptions -title: InjectInfiniteQueryOptions ---- - -Defined in: [packages/angular-query-experimental/src/inject-infinite-query.ts:25](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L25) - -## Properties - -| Property | Type | Description | -| ------ | ------ | ------ | -| `injector?` | `Injector` | The `Injector` in which to create the infinite query. If this is not provided, the current injection context will be used instead (via `inject`). | diff --git a/docs/framework/angular/reference/interfaces/InjectIsFetchingOptions.md b/docs/framework/angular/reference/interfaces/InjectIsFetchingOptions.md deleted file mode 100644 index 7bda7143a0b..00000000000 --- a/docs/framework/angular/reference/interfaces/InjectIsFetchingOptions.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: InjectIsFetchingOptions -title: InjectIsFetchingOptions ---- - -Defined in: [packages/angular-query-experimental/src/inject-is-fetching.ts:13](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-fetching.ts#L13) - -## Properties - -| Property | Type | Description | -| ------ | ------ | ------ | -| `injector?` | `Injector` | The `Injector` in which to create the isFetching signal. If this is not provided, the current injection context will be used instead (via `inject`). | diff --git a/docs/framework/angular/reference/interfaces/InjectIsMutatingOptions.md b/docs/framework/angular/reference/interfaces/InjectIsMutatingOptions.md deleted file mode 100644 index 2db5b68f100..00000000000 --- a/docs/framework/angular/reference/interfaces/InjectIsMutatingOptions.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: InjectIsMutatingOptions -title: InjectIsMutatingOptions ---- - -Defined in: [packages/angular-query-experimental/src/inject-is-mutating.ts:13](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-mutating.ts#L13) - -## Properties - -| Property | Type | Description | -| ------ | ------ | ------ | -| `injector?` | `Injector` | The `Injector` in which to create the isMutating signal. If this is not provided, the current injection context will be used instead (via `inject`). | diff --git a/docs/framework/angular/reference/interfaces/InjectMutationOptions.md b/docs/framework/angular/reference/interfaces/InjectMutationOptions.md deleted file mode 100644 index 223b80433e0..00000000000 --- a/docs/framework/angular/reference/interfaces/InjectMutationOptions.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: InjectMutationOptions -title: InjectMutationOptions ---- - -Defined in: [packages/angular-query-experimental/src/inject-mutation.ts:28](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation.ts#L28) - -## Properties - -| Property | Type | Description | -| ------ | ------ | ------ | -| `injector?` | `Injector` | The `Injector` in which to create the mutation. If this is not provided, the current injection context will be used instead (via `inject`). | diff --git a/docs/framework/angular/reference/interfaces/InjectMutationStateOptions.md b/docs/framework/angular/reference/interfaces/InjectMutationStateOptions.md deleted file mode 100644 index 7b1390974d3..00000000000 --- a/docs/framework/angular/reference/interfaces/InjectMutationStateOptions.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: InjectMutationStateOptions -title: InjectMutationStateOptions ---- - -Defined in: [packages/angular-query-experimental/src/inject-mutation-state.ts:40](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation-state.ts#L40) - -## Properties - -| Property | Type | Description | -| ------ | ------ | ------ | -| `injector?` | `Injector` | The `Injector` in which to create the mutation state signal. If this is not provided, the current injection context will be used instead (via `inject`). | diff --git a/docs/framework/angular/reference/interfaces/InjectQueriesOptions.md b/docs/framework/angular/reference/interfaces/InjectQueriesOptions.md new file mode 100644 index 00000000000..cf774321bac --- /dev/null +++ b/docs/framework/angular/reference/interfaces/InjectQueriesOptions.md @@ -0,0 +1,48 @@ +--- +id: InjectQueriesOptions +title: InjectQueriesOptions +--- + +Defined in: [packages/angular-query/src/inject-queries.types.ts:213](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-queries.types.ts#L213) + +## Type Parameters + +### T + +`T` *extends* `any`[] + +### TCombinedResult + +`TCombinedResult` = [`QueriesResults`](../type-aliases/QueriesResults.md)\<`T`\> + +## Properties + +### combine()? + +```ts +optional combine: (result) => TCombinedResult; +``` + +Defined in: [packages/angular-query/src/inject-queries.types.ts:222](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-queries.types.ts#L222) + +#### Parameters + +##### result + +`T` *extends* \[\] ? \[\] : `T` *extends* \[`Head`\] ? \[`GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<`Head`\>\[`"data"`\], `QueryObserverResult`\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>, `DefinedQueryObserverResult`\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>\>\] : `T` *extends* \[`Head`, `...Tails[]`\] ? \[`...Tails[]`\] *extends* \[\] ? \[\] : \[`...Tails[]`\] *extends* \[`Head`\] ? \[`GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<...\>\[`"data"`\], `QueryObserverResult`\<...\[...\], ...\[...\]\>, `DefinedQueryObserverResult`\<...\[...\], ...\[...\]\>\>, `GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<...\>\[`"data"`\], `QueryObserverResult`\<...\[...\], ...\[...\]\>, `DefinedQueryObserverResult`\<...\[...\], ...\[...\]\>\>\] : \[`...Tails[]`\] *extends* \[`Head`, `...Tails[]`\] ? \[`...Tails[]`\] *extends* \[\] ? \[\] : \[`...(...)[]`\] *extends* \[...\] ? \[..., ..., ...\] : ... *extends* ... ? ... : ... : \[...\{ \[K in (...) \| (...) \| (...)\]: GenericGetDefinedOrUndefinedQueryResult\<(...), (...), (...), (...)\> \}\[\]\] : \{ \[K in string \| number \| symbol\]: GenericGetDefinedOrUndefinedQueryResult\\], InferDataAndError\\]\>\["data"\], QueryObserverResult\\["data"\], InferDataAndError\<(...)\[(...)\]\>\["error"\]\>, DefinedQueryObserverResult\\["data"\], InferDataAndError\<(...)\[(...)\]\>\["error"\]\>\> \} + +#### Returns + +`TCombinedResult` + +*** + +### queries + +```ts +queries: + | readonly [{ [K in string | number | symbol]: GetCreateQueryOptionsForCreateQueries]> }] + | readonly [T extends [] ? [] : T extends [Head] ? [GetCreateQueryOptionsForCreateQueries] : T extends [Head, ...Tails[]] ? [...Tails[]] extends [] ? [] : [...Tails[]] extends [Head] ? [GetCreateQueryOptionsForCreateQueries, GetCreateQueryOptionsForCreateQueries] : [...Tails[]] extends [Head, ...Tails[]] ? [...Tails[]] extends [] ? [] : [...(...)[]] extends [...] ? [..., ..., ...] : ... extends ... ? ... : ... : readonly unknown[] extends [...Tails[]] ? [...Tails[]] : [...(...)[]] extends ...[] ? ...[] : ...[] : readonly unknown[] extends T ? T : T extends QueryObserverOptionsForCreateQueries[] ? QueryObserverOptionsForCreateQueries[] : QueryObserverOptionsForCreateQueries[]]; +``` + +Defined in: [packages/angular-query/src/inject-queries.types.ts:217](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-queries.types.ts#L217) diff --git a/docs/framework/angular/reference/interfaces/InjectQueryOptions.md b/docs/framework/angular/reference/interfaces/InjectQueryOptions.md deleted file mode 100644 index 6da34676e3f..00000000000 --- a/docs/framework/angular/reference/interfaces/InjectQueryOptions.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: InjectQueryOptions -title: InjectQueryOptions ---- - -Defined in: [packages/angular-query-experimental/src/inject-query.ts:20](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L20) - -## Properties - -| Property | Type | Description | -| ------ | ------ | ------ | -| `injector?` | `Injector` | The `Injector` in which to create the query. If this is not provided, the current injection context will be used instead (via `inject`). | diff --git a/docs/framework/angular/reference/interfaces/QueryFeature.md b/docs/framework/angular/reference/interfaces/QueryFeature.md index 17f74b4655a..c65d634a369 100644 --- a/docs/framework/angular/reference/interfaces/QueryFeature.md +++ b/docs/framework/angular/reference/interfaces/QueryFeature.md @@ -3,19 +3,15 @@ id: QueryFeature title: QueryFeature --- -Defined in: [packages/angular-query-experimental/src/providers.ts:132](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L132) +An opaque configuration returned by Query feature functions. Pass these values to +`provideTanStackQuery`; application code does not construct or inspect them. -Helper type to represent a Query feature. +```ts +provideTanStackQuery( + () => new QueryClient(), + withHydrationKey('secondary-cache'), +) +``` -## Type Parameters - -### TFeatureKind - -`TFeatureKind` *extends* `QueryFeatureKind` - -## Properties - -| Property | Type | -| ------ | ------ | -| `ɵkind` | `TFeatureKind` | -| `ɵproviders` | `Provider`[] | +See [provideTanStackQuery](../functions/provideTanStackQuery.md) for provider setup +and [SSR](../../guides/ssr.md) for hydration features. diff --git a/docs/framework/angular/reference/interfaces/QueryObserverOptions.md b/docs/framework/angular/reference/interfaces/QueryObserverOptions.md index 627cde26543..8722cbd51af 100644 --- a/docs/framework/angular/reference/interfaces/QueryObserverOptions.md +++ b/docs/framework/angular/reference/interfaces/QueryObserverOptions.md @@ -12,7 +12,6 @@ Defined in: [packages/query-core/src/types.ts:435](https://github.com/TanStack/q ## Extended by - [`InfiniteQueryObserverOptions`](InfiniteQueryObserverOptions.md) -- [`CreateBaseQueryOptions`](CreateBaseQueryOptions.md) ## Type Parameters diff --git a/docs/framework/angular/reference/interfaces/QueryResource.md b/docs/framework/angular/reference/interfaces/QueryResource.md new file mode 100644 index 00000000000..dbfe89d3e72 --- /dev/null +++ b/docs/framework/angular/reference/interfaces/QueryResource.md @@ -0,0 +1,172 @@ +--- +id: QueryResource +title: QueryResource +--- + +Defined in: [packages/angular-query/src/query-resource.ts:6](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-resource.ts#L6) + +## Extends + +- `Resource`\<`TValue`\> + +## Type Parameters + +### TValue + +`TValue` + +## Properties + +### error + +```ts +readonly error: Signal; +``` + +Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:139 + +When in the `error` state, this returns the last known error from the `Resource`. + +#### Inherited from + +```ts +Resource.error +``` + +*** + +### isLoading + +```ts +readonly isLoading: Signal; +``` + +Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:143 + +Whether this resource is loading a new value (or reloading the existing one). + +#### Inherited from + +```ts +Resource.isLoading +``` + +*** + +### reload() + +```ts +reload: () => boolean; +``` + +Defined in: [packages/angular-query/src/query-resource.ts:20](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-resource.ts#L20) + +Requests a new query fetch only when the current query data is stale. + +Used for compatibility with Angular APIs that might want to reload a resource, +like Signal Forms' validateAsync resource interface. + +#### Returns + +`boolean` + +`true` if a reload was initiated, `false` if a reload was unnecessary or unsupported. + +*** + +### snapshot + +```ts +readonly snapshot: Signal>; +``` + +Defined in: [packages/angular-query/src/query-resource.ts:10](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-resource.ts#L10) + +The current query state as a single snapshot. + +*** + +### status + +```ts +readonly status: Signal; +``` + +Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:135 + +The current status of the `Resource`, which describes what the resource is currently doing and +what can be expected of its `value`. + +#### Inherited from + +```ts +Resource.status +``` + +*** + +### value + +```ts +readonly value: Signal; +``` + +Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:130 + +The current value of the `Resource`, or throws an error if the resource is in an error state. + +#### Inherited from + +```ts +Resource.value +``` + +## Methods + +### hasValue() + +#### Call Signature + +```ts +hasValue(this): this is Resource>; +``` + +Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:149 + +Whether this resource has a valid current value. + +This function is reactive. + +##### Parameters + +###### this + +`TValue` *extends* `undefined` ? `QueryResource`\<`TValue`\> : `never` + +##### Returns + +`this is Resource>` + +##### Inherited from + +```ts +Resource.hasValue +``` + +#### Call Signature + +```ts +hasValue(): boolean; +``` + +Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:150 + +##### Returns + +`boolean` + +##### Inherited from + +```ts +Resource.hasValue +``` diff --git a/docs/framework/angular/reference/type-aliases/CreateBaseMutationResult.md b/docs/framework/angular/reference/type-aliases/CreateBaseMutationResult.md index 30408338654..bc7ffa49731 100644 --- a/docs/framework/angular/reference/type-aliases/CreateBaseMutationResult.md +++ b/docs/framework/angular/reference/type-aliases/CreateBaseMutationResult.md @@ -9,11 +9,7 @@ type CreateBaseMutationResult = Over }> & object; ``` -Defined in: [packages/angular-query-experimental/src/types.ts:284](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L284) - -The pre-`Signal` shape [CreateMutationResult](CreateMutationResult.md) is built from — not what `injectMutation` actually -returns. Same as [MutationObserverResult](MutationObserverResult.md) from `@tanstack/query-core`, with `mutate` narrowed to the -fire-and-forget [CreateMutateFunction](CreateMutateFunction.md) signature, plus the added `mutateAsync`. +Defined in: [packages/angular-query/src/types.ts:269](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L269) ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/CreateBaseQueryResult.md b/docs/framework/angular/reference/type-aliases/CreateBaseQueryResult.md index f632a3e04a7..def30c80476 100644 --- a/docs/framework/angular/reference/type-aliases/CreateBaseQueryResult.md +++ b/docs/framework/angular/reference/type-aliases/CreateBaseQueryResult.md @@ -4,17 +4,10 @@ title: CreateBaseQueryResult --- ```ts -type CreateBaseQueryResult = BaseQueryNarrowing & MapToSignals>; +type CreateBaseQueryResult = BaseQueryNarrowing & MapToSignals, MethodKeys>>; ``` -Defined in: [packages/angular-query-experimental/src/types.ts:149](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L149) - -The result of `injectQuery` when `initialData` isn't set — `data` may be `undefined` while the query is -`pending`. Same shape as [QueryObserverResult](QueryObserverResult.md) from `@tanstack/query-core`, but value fields (like -`data`, `error`, `status`) are exposed as a `Signal` — read them with `query.data()`, not `query.data` — -while function fields (like `refetch`) are called directly, unchanged. `isSuccess`/`isError`/`isPending` -are [BaseQueryNarrowing](../interfaces/BaseQueryNarrowing.md) type-guard methods rather than plain booleans. -`injectInfiniteQuery` returns [CreateInfiniteQueryResult](CreateInfiniteQueryResult.md) instead. +Defined in: [packages/angular-query/src/types.ts:191](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L191) ## Type Parameters @@ -32,4 +25,4 @@ The type of errors your `queryFn` may throw. ### TState -`TState` = [`QueryObserverResult`](QueryObserverResult.md)\<`TData`, `TError`\> +`TState` *extends* `QueryObserverResult`\<`TData`, `TError`\> = `QueryObserverResult`\<`TData`, `TError`\> diff --git a/docs/framework/angular/reference/type-aliases/CreateInfiniteQueryResult.md b/docs/framework/angular/reference/type-aliases/CreateInfiniteQueryResult.md index e0b6a6981f4..c09f572f8de 100644 --- a/docs/framework/angular/reference/type-aliases/CreateInfiniteQueryResult.md +++ b/docs/framework/angular/reference/type-aliases/CreateInfiniteQueryResult.md @@ -4,15 +4,10 @@ title: CreateInfiniteQueryResult --- ```ts -type CreateInfiniteQueryResult = BaseQueryNarrowing & MapToSignals>; +type CreateInfiniteQueryResult = BaseInfiniteQueryNarrowing & MapToSignals>; ``` -Defined in: [packages/angular-query-experimental/src/types.ts:191](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L191) - -The result of `injectInfiniteQuery` when `initialData` isn't set — `data` may be `undefined` while the -query is `pending`. Same shape as [InfiniteQueryObserverResult](InfiniteQueryObserverResult.md) from `@tanstack/query-core`, but -value fields are exposed as a `Signal` while function fields (like `fetchNextPage`) are called directly, -unchanged. +Defined in: [packages/angular-query/src/types.ts:220](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L220) ## Type Parameters @@ -24,6 +19,8 @@ The type `data` ends up as after `select` runs. ### TError -`TError` = [`DefaultError`](DefaultError.md) +`TError` = `DefaultError` + +### TState -The type of errors your `queryFn` may throw. +`TState` *extends* `InfiniteQueryObserverResult`\<`TData`, `TError`\> = `InfiniteQueryObserverResult`\<`TData`, `TError`\> diff --git a/docs/framework/angular/reference/type-aliases/CreateMutateAsyncFunction.md b/docs/framework/angular/reference/type-aliases/CreateMutateAsyncFunction.md index fe72322f8cd..2d410fe52f6 100644 --- a/docs/framework/angular/reference/type-aliases/CreateMutateAsyncFunction.md +++ b/docs/framework/angular/reference/type-aliases/CreateMutateAsyncFunction.md @@ -7,10 +7,7 @@ title: CreateMutateAsyncFunction type CreateMutateAsyncFunction = MutateFunction; ``` -Defined in: [packages/angular-query-experimental/src/types.ts:266](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L266) - -The type of `mutateAsync`, as returned by `injectMutation`. Similar to [CreateMutateFunction](CreateMutateFunction.md), but -returns a promise which can be awaited. +Defined in: [packages/angular-query/src/types.ts:262](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L262) ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/CreateMutateFunction.md b/docs/framework/angular/reference/type-aliases/CreateMutateFunction.md index 7e7d9ecfa6f..2e939f7ccd3 100644 --- a/docs/framework/angular/reference/type-aliases/CreateMutateFunction.md +++ b/docs/framework/angular/reference/type-aliases/CreateMutateFunction.md @@ -7,11 +7,7 @@ title: CreateMutateFunction type CreateMutateFunction = (...args: Parameters>) => void; ``` -Defined in: [packages/angular-query-experimental/src/types.ts:245](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L245) - -The type of `mutate`, as returned by `injectMutation`. Forwards the variables (and an optional per-call -`onSuccess`/`onError`/`onSettled`) to the underlying `mutate` call. Fire-and-forget — errors are surfaced -through the mutation result, not thrown. +Defined in: [packages/angular-query/src/types.ts:251](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L251) ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/CreateMutationResult.md b/docs/framework/angular/reference/type-aliases/CreateMutationResult.md index 7a167bee22c..d46f090d102 100644 --- a/docs/framework/angular/reference/type-aliases/CreateMutationResult.md +++ b/docs/framework/angular/reference/type-aliases/CreateMutationResult.md @@ -4,15 +4,10 @@ title: CreateMutationResult --- ```ts -type CreateMutationResult = BaseMutationNarrowing & MapToSignals>; +type CreateMutationResult = BaseMutationNarrowing & MapToSignals, MethodKeys>>; ``` -Defined in: [packages/angular-query-experimental/src/types.ts:416](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L416) - -The result of `injectMutation`. Based on [CreateBaseMutationResult](CreateBaseMutationResult.md), but value fields are exposed as -a `Signal` — read them with `mutation.data()`, not `mutation.data` — while function fields (`mutate`, -`mutateAsync`, `reset`) are called directly, unchanged. `isSuccess`/`isError`/`isPending`/`isIdle` are -[BaseMutationNarrowing](../interfaces/BaseMutationNarrowing.md) type-guard methods rather than plain booleans. +Defined in: [packages/angular-query/src/types.ts:373](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L373) ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/CreateQueryOptions.md b/docs/framework/angular/reference/type-aliases/CreateQueryOptions.md new file mode 100644 index 00000000000..f71513d7083 --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/CreateQueryOptions.md @@ -0,0 +1,28 @@ +--- +id: CreateQueryOptions +title: CreateQueryOptions +--- + +```ts +type CreateQueryOptions = OmitKeyof, "notifyOnChangeProps" | "suspense" | "throwOnError">; +``` + +Defined in: [packages/angular-query/src/types.ts:23](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L23) + +## Type Parameters + +### TQueryFnData + +`TQueryFnData` = `unknown` + +### TError + +`TError` = `DefaultError` + +### TData + +`TData` = `TQueryFnData` + +### TQueryKey + +`TQueryKey` *extends* `QueryKey` = `QueryKey` diff --git a/docs/framework/angular/reference/type-aliases/CreateQueryResult.md b/docs/framework/angular/reference/type-aliases/CreateQueryResult.md index 2e57945064b..c289489f1d9 100644 --- a/docs/framework/angular/reference/type-aliases/CreateQueryResult.md +++ b/docs/framework/angular/reference/type-aliases/CreateQueryResult.md @@ -7,9 +7,7 @@ title: CreateQueryResult type CreateQueryResult = CreateBaseQueryResult; ``` -Defined in: [packages/angular-query-experimental/src/types.ts:162](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L162) - -The result of `injectQuery`. Same as [CreateBaseQueryResult](CreateBaseQueryResult.md). +Defined in: [packages/angular-query/src/types.ts:204](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L204) ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/DefinedCreateInfiniteQueryResult.md b/docs/framework/angular/reference/type-aliases/DefinedCreateInfiniteQueryResult.md index 382b86bdbd1..c45e90f217e 100644 --- a/docs/framework/angular/reference/type-aliases/DefinedCreateInfiniteQueryResult.md +++ b/docs/framework/angular/reference/type-aliases/DefinedCreateInfiniteQueryResult.md @@ -4,14 +4,10 @@ title: DefinedCreateInfiniteQueryResult --- ```ts -type DefinedCreateInfiniteQueryResult = MapToSignals; +type DefinedCreateInfiniteQueryResult = DefinedInfiniteQueryNarrowing & MapToSignals>; ``` -Defined in: [packages/angular-query-experimental/src/types.ts:205](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L205) - -The result of `injectInfiniteQuery` when `initialData` is set — `data` is never `undefined`. Same shape as -[DefinedInfiniteQueryObserverResult](DefinedInfiniteQueryObserverResult.md) from `@tanstack/query-core`, but value fields are exposed as a -`Signal` while function fields are called directly, unchanged. +Defined in: [packages/angular-query/src/types.ts:228](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L228) ## Type Parameters @@ -29,4 +25,4 @@ The type of errors your `queryFn` may throw. ### TDefinedInfiniteQueryObserver -`TDefinedInfiniteQueryObserver` = [`DefinedInfiniteQueryObserverResult`](DefinedInfiniteQueryObserverResult.md)\<`TData`, `TError`\> +`TDefinedInfiniteQueryObserver` *extends* `DefinedInfiniteQueryObserverResult`\<`TData`, `TError`\> = `DefinedInfiniteQueryObserverResult`\<`TData`, `TError`\> diff --git a/docs/framework/angular/reference/type-aliases/DefinedCreateQueryResult.md b/docs/framework/angular/reference/type-aliases/DefinedCreateQueryResult.md index 934f51485d1..fbeae6470c5 100644 --- a/docs/framework/angular/reference/type-aliases/DefinedCreateQueryResult.md +++ b/docs/framework/angular/reference/type-aliases/DefinedCreateQueryResult.md @@ -4,14 +4,10 @@ title: DefinedCreateQueryResult --- ```ts -type DefinedCreateQueryResult = BaseQueryNarrowing & MapToSignals>; +type DefinedCreateQueryResult = DefinedQueryNarrowing & MapToSignals, MethodKeys>>; ``` -Defined in: [packages/angular-query-experimental/src/types.ts:175](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L175) - -The result of `injectQuery` when `initialData` is set — `data` is never `undefined`. Same shape as -[DefinedQueryObserverResult](DefinedQueryObserverResult.md) from `@tanstack/query-core`, but value fields are exposed as a -`Signal` while function fields are called directly, unchanged. +Defined in: [packages/angular-query/src/types.ts:209](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L209) ## Type Parameters @@ -29,4 +25,4 @@ The type of errors your `queryFn` may throw. ### TState -`TState` = [`DefinedQueryObserverResult`](DefinedQueryObserverResult.md)\<`TData`, `TError`\> +`TState` *extends* `DefinedQueryObserverResult`\<`TData`, `TError`\> = `DefinedQueryObserverResult`\<`TData`, `TError`\> diff --git a/docs/framework/angular/reference/type-aliases/DefinedInitialDataInfiniteOptions.md b/docs/framework/angular/reference/type-aliases/DefinedInitialDataInfiniteOptions.md index d4b42457136..db4668bf7c8 100644 --- a/docs/framework/angular/reference/type-aliases/DefinedInitialDataInfiniteOptions.md +++ b/docs/framework/angular/reference/type-aliases/DefinedInitialDataInfiniteOptions.md @@ -7,10 +7,7 @@ title: DefinedInitialDataInfiniteOptions type DefinedInitialDataInfiniteOptions = CreateInfiniteQueryOptions & object; ``` -Defined in: [packages/angular-query-experimental/src/infinite-query-options.ts:109](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L109) - -The options accepted by the `infiniteQueryOptions` overload selected when `initialData` is set — `data` is -never `undefined` (unless a `select` changes `TData` to include `undefined`). +Defined in: [packages/angular-query/src/infinite-query-options.ts:62](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L62) ## Type Declaration @@ -19,8 +16,7 @@ never `undefined` (unless a `select` changes `TData` to include `undefined`). ```ts initialData: | NonUndefinedGuard> - | () => NonUndefinedGuard> - | undefined; +| () => NonUndefinedGuard>; ``` If set, this value will be used as the initial data for the query cache (as long as the query hasn't been diff --git a/docs/framework/angular/reference/type-aliases/DefinedInitialDataOptions.md b/docs/framework/angular/reference/type-aliases/DefinedInitialDataOptions.md index e37476fa74d..c301220238c 100644 --- a/docs/framework/angular/reference/type-aliases/DefinedInitialDataOptions.md +++ b/docs/framework/angular/reference/type-aliases/DefinedInitialDataOptions.md @@ -4,13 +4,10 @@ title: DefinedInitialDataOptions --- ```ts -type DefinedInitialDataOptions = Omit, "queryFn"> & object; +type DefinedInitialDataOptions = CreateQueryOptions & object; ``` -Defined in: [packages/angular-query-experimental/src/query-options.ts:80](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L80) - -The options accepted by the `queryOptions` overload selected when `initialData` is set — `data` is never -`undefined` (unless a `select` changes `TData` to include `undefined`). +Defined in: [packages/angular-query/src/query-options.ts:39](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L39) ## Type Declaration @@ -22,22 +19,6 @@ initialData: | () => NonUndefinedGuard; ``` -If set, this value will be used as the initial data for the query cache (as long as the query hasn't been -created or cached yet). If set to a function, the function will be called **once** during the shared/root -query initialization, and be expected to synchronously return the initial data. Initial data is -considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the -cache. - -### queryFn? - -```ts -optional queryFn: QueryFunction; -``` - -Optional here, but omitting it is only safe when no fetch will be attempted — for example with -`enabled: false`, or when a default query function has been defined. Otherwise, an enabled query with no -`queryFn` still tries to fetch and fails with a "Missing queryFn" error; `initialData` does not prevent this. - ## Type Parameters ### TQueryFnData diff --git a/docs/framework/angular/reference/type-aliases/DevtoolsFeature.md b/docs/framework/angular/reference/type-aliases/DevtoolsFeature.md deleted file mode 100644 index 2db12a400ab..00000000000 --- a/docs/framework/angular/reference/type-aliases/DevtoolsFeature.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: DevtoolsFeature -title: DevtoolsFeature ---- - -```ts -type DevtoolsFeature = QueryFeature<"Devtools">; -``` - -Defined in: [packages/angular-query-experimental/src/providers.ts:155](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L155) - -A type alias that represents a feature which enables developer tools. -The type is used to describe the return value of the `withDevtools` function. - -## See - -withDevtools diff --git a/docs/framework/angular/reference/type-aliases/MutationStateOptions.md b/docs/framework/angular/reference/type-aliases/MutationStateOptions.md new file mode 100644 index 00000000000..dfd8018782b --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/MutationStateOptions.md @@ -0,0 +1,50 @@ +--- +id: MutationStateOptions +title: MutationStateOptions +--- + +```ts +type MutationStateOptions = object; +``` + +Defined in: [packages/angular-query/src/inject-mutation-state.ts:23](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-mutation-state.ts#L23) + +## Type Parameters + +### TResult + +`TResult` = `MutationState` + +### TMutation + +`TMutation` *extends* `Mutation`\<`any`, `any`, `any`, `any`\> = `MutationTypeFromResult`\<`TResult`\> + +## Properties + +### filters? + +```ts +optional filters: MutationFilters; +``` + +Defined in: [packages/angular-query/src/inject-mutation-state.ts:28](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-mutation-state.ts#L28) + +*** + +### select()? + +```ts +optional select: (mutation) => TResult; +``` + +Defined in: [packages/angular-query/src/inject-mutation-state.ts:29](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-mutation-state.ts#L29) + +#### Parameters + +##### mutation + +`TMutation` + +#### Returns + +`TResult` diff --git a/docs/framework/angular/reference/type-aliases/PersistQueryClientFeature.md b/docs/framework/angular/reference/type-aliases/PersistQueryClientFeature.md deleted file mode 100644 index e094e32a970..00000000000 --- a/docs/framework/angular/reference/type-aliases/PersistQueryClientFeature.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -id: PersistQueryClientFeature -title: PersistQueryClientFeature ---- - -```ts -type PersistQueryClientFeature = QueryFeature<"PersistQueryClient">; -``` - -Defined in: [packages/angular-query-experimental/src/providers.ts:161](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L161) - -A type alias that represents a feature which enables persistence. -The type is used to describe the return value of the `withPersistQueryClient` function. diff --git a/docs/framework/angular/reference/type-aliases/QueriesOptions.md b/docs/framework/angular/reference/type-aliases/QueriesOptions.md index a0f51826b76..411f34c036f 100644 --- a/docs/framework/angular/reference/type-aliases/QueriesOptions.md +++ b/docs/framework/angular/reference/type-aliases/QueriesOptions.md @@ -7,13 +7,7 @@ title: QueriesOptions type QueriesOptions = TDepth["length"] extends MAXIMUM_DEPTH ? QueryObserverOptionsForCreateQueries[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetCreateQueryOptionsForCreateQueries] : T extends [infer Head, ...(infer Tails)] ? QueriesOptions<[...Tails], [...TResults, GetCreateQueryOptionsForCreateQueries], [...TDepth, 1]> : ReadonlyArray extends T ? T : T extends QueryObserverOptionsForCreateQueries[] ? QueryObserverOptionsForCreateQueries[] : QueryObserverOptionsForCreateQueries[]; ``` -Defined in: [packages/angular-query-experimental/src/inject-queries.ts:154](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-queries.ts#L154) - -The `queries` array accepted by `injectQueries`. Recursively unwraps each tuple element so every entry's -`queryFn`/`select`/`throwOnError` are inferred individually, up to 20 elements — past that, tuple -recursion falls back to a single homogeneous options type. An opaque array (e.g. `unknown[]`) is returned -as-is; a non-tuple array of a known element type is mapped to that element type instead, with no such -limit. +Defined in: [packages/angular-query/src/inject-queries.types.ts:141](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-queries.types.ts#L141) ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/QueriesResults.md b/docs/framework/angular/reference/type-aliases/QueriesResults.md index e31cb61caef..8bf2b78c875 100644 --- a/docs/framework/angular/reference/type-aliases/QueriesResults.md +++ b/docs/framework/angular/reference/type-aliases/QueriesResults.md @@ -7,12 +7,7 @@ title: QueriesResults type QueriesResults = TDepth["length"] extends MAXIMUM_DEPTH ? CreateQueryResult[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetCreateQueryResult] : T extends [infer Head, ...(infer Tails)] ? QueriesResults<[...Tails], [...TResults, GetCreateQueryResult], [...TDepth, 1]> : { [K in keyof T]: GetCreateQueryResult }; ``` -Defined in: [packages/angular-query-experimental/src/inject-queries.ts:205](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-queries.ts#L205) - -The result type returned by `injectQueries`, when no `combine` is provided. Mirrors [QueriesOptions](QueriesOptions.md): -each tuple element's result type is inferred individually, up to 20 elements — past that, tuple recursion -falls back to a single homogeneous [CreateQueryResult](CreateQueryResult.md) type. A non-tuple array is mapped per-element -instead, with no such limit — every entry keeps its individually inferred type regardless of array length. +Defined in: [packages/angular-query/src/inject-queries.types.ts:177](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-queries.types.ts#L177) ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/QueryFeatures.md b/docs/framework/angular/reference/type-aliases/QueryFeatures.md deleted file mode 100644 index ea04f398ffc..00000000000 --- a/docs/framework/angular/reference/type-aliases/QueryFeatures.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: QueryFeatures -title: QueryFeatures ---- - -```ts -type QueryFeatures = - | DevtoolsFeature - | PersistQueryClientFeature; -``` - -Defined in: [packages/angular-query-experimental/src/providers.ts:170](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L170) - -A type alias that represents all Query features available for use with `provideTanStackQuery`. -Features can be enabled by adding special functions to the `provideTanStackQuery` call. -See documentation for each symbol to find corresponding function name. See also `provideTanStackQuery` -documentation on how to use those functions. - -## See - -[provideTanStackQuery](../functions/provideTanStackQuery.md) diff --git a/docs/framework/angular/reference/type-aliases/UndefinedInitialDataInfiniteOptions.md b/docs/framework/angular/reference/type-aliases/UndefinedInitialDataInfiniteOptions.md index e657351693d..50e5e3feaa7 100644 --- a/docs/framework/angular/reference/type-aliases/UndefinedInitialDataInfiniteOptions.md +++ b/docs/framework/angular/reference/type-aliases/UndefinedInitialDataInfiniteOptions.md @@ -7,10 +7,7 @@ title: UndefinedInitialDataInfiniteOptions type UndefinedInitialDataInfiniteOptions = CreateInfiniteQueryOptions & object; ``` -Defined in: [packages/angular-query-experimental/src/infinite-query-options.ts:24](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L24) - -The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set — `data` -may be `undefined` while the query is `pending`. +Defined in: [packages/angular-query/src/infinite-query-options.ts:13](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L13) ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/UndefinedInitialDataOptions.md b/docs/framework/angular/reference/type-aliases/UndefinedInitialDataOptions.md index 3814e441388..54d2db71cb2 100644 --- a/docs/framework/angular/reference/type-aliases/UndefinedInitialDataOptions.md +++ b/docs/framework/angular/reference/type-aliases/UndefinedInitialDataOptions.md @@ -7,10 +7,7 @@ title: UndefinedInitialDataOptions type UndefinedInitialDataOptions = CreateQueryOptions & object; ``` -Defined in: [packages/angular-query-experimental/src/query-options.ts:22](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L22) - -The options accepted by the `queryOptions` overload selected when no `initialData` is set — `data` may be -`undefined` while the query is `pending`. +Defined in: [packages/angular-query/src/query-options.ts:12](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L12) ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/UnusedSkipTokenInfiniteOptions.md b/docs/framework/angular/reference/type-aliases/UnusedSkipTokenInfiniteOptions.md index ec9ab5c61dd..70c4640c4c1 100644 --- a/docs/framework/angular/reference/type-aliases/UnusedSkipTokenInfiniteOptions.md +++ b/docs/framework/angular/reference/type-aliases/UnusedSkipTokenInfiniteOptions.md @@ -7,11 +7,7 @@ title: UnusedSkipTokenInfiniteOptions type UnusedSkipTokenInfiniteOptions = OmitKeyof, "queryFn"> & object; ``` -Defined in: [packages/angular-query-experimental/src/infinite-query-options.ts:64](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L64) - -The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set and -`queryFn` is not `skipToken` — same as [UndefinedInitialDataInfiniteOptions](UndefinedInitialDataInfiniteOptions.md), but `queryFn` may not be -`skipToken`. +Defined in: [packages/angular-query/src/infinite-query-options.ts:34](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L34) ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/UnusedSkipTokenOptions.md b/docs/framework/angular/reference/type-aliases/UnusedSkipTokenOptions.md index 854d773b68e..65c192aee95 100644 --- a/docs/framework/angular/reference/type-aliases/UnusedSkipTokenOptions.md +++ b/docs/framework/angular/reference/type-aliases/UnusedSkipTokenOptions.md @@ -7,10 +7,7 @@ title: UnusedSkipTokenOptions type UnusedSkipTokenOptions = OmitKeyof, "queryFn"> & object; ``` -Defined in: [packages/angular-query-experimental/src/query-options.ts:50](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L50) - -The options accepted by the `queryOptions` overload selected when no `initialData` is set and `queryFn` is -not `skipToken` — same as [UndefinedInitialDataOptions](UndefinedInitialDataOptions.md), but `queryFn` may not be `skipToken`. +Defined in: [packages/angular-query/src/query-options.ts:24](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L24) ## Type Declaration diff --git a/docs/framework/angular/resource-api.md b/docs/framework/angular/resource-api.md new file mode 100644 index 00000000000..6463d4799e8 --- /dev/null +++ b/docs/framework/angular/resource-api.md @@ -0,0 +1,160 @@ +--- +id: resource-api +title: Resource API +--- + +Angular Query can convert any query result into an Angular +[`Resource`](https://angular.dev/api/core/Resource)-compatible view with `toResource`. The query +remains responsible for fetching and caching the server state while Angular APIs can consume the +familiar Resource shape. + +```ts +import { Component, input } from '@angular/core' +import { injectQuery, toResource } from '@tanstack/angular-query' + +@Component({ + selector: 'todo-detail', + template: ` + @if (todo.hasValue()) { +

{{ todo.value().title }}

+ } + `, +}) +export class TodoDetail { + readonly id = input.required() + + readonly todoQuery = injectQuery(() => { + const id = this.id() + return { + queryKey: ['todo', id], + queryFn: () => fetchTodo(id), + } + }) + + readonly todo = toResource(this.todoQuery) +} +``` + +The Resource view exposes these fields: + +| Field | Description | +| ----------- | --------------------------------------------------------------------- | +| `value` | The current query data | +| `status` | The query state as an Angular `ResourceStatus` | +| `error` | The current error, normalized to `Error` | +| `isLoading` | Whether the query is loading or reloading | +| `hasValue` | Whether a value is available | +| `snapshot` | The current Resource state as one signal | +| `reload` | Refetches when the query is stale and returns whether a fetch started | + +Use the query's field signals and methods for normal application code. Use `toResource(query)` when +an Angular API expects a Resource or when Resource terminology makes an integration clearer. Call +`query.refetch()` instead of `resource.reload()` when you need an unconditional refetch. + +## Errors + +`value()` throws when the Resource's status is `error`. Read `hasValue()` before accessing it, or +inspect `error()` and `snapshot()` to render an error state. A failed background refetch can leave +cached data available through `query.data()` while the Resource is in its error state. + +Resource errors are not automatically reported globally. See [Error handling](./guides/error-handling.md) +for an opt-in `ErrorHandler` integration. + +## Using Resource with Signal Forms + +> Signal Forms integration requires Angular 21 or newer. + +Angular Signal Forms' +[`validateAsync`](https://angular.dev/guide/forms/signals/async-operations#custom-async-validation-with-validateasync) +accepts a Resource factory. Passing `injectQuery(...)` to `toResource` lets async validation use +Angular Query caching, request deduplication, cancellation, retries, and stale-time behavior. + +The example below validates a username. The query is disabled while the field has no value, and the +factory returns `toResource(query)`. + +```ts +import { Component, inject, signal } from '@angular/core' +import { form, validateAsync } from '@angular/forms/signals' +import { injectQuery, toResource } from '@tanstack/angular-query' + +type UsernameValidation = { + available: boolean +} + +@Component({ + selector: 'registration-form', + template: '', +}) +export class RegistrationForm { + private readonly users = inject(UserService) + readonly model = signal({ username: '' }) + + readonly registrationForm = form(this.model, (path) => { + validateAsync(path.username, { + debounce: 300, + params: ({ value }) => value().trim() || undefined, + factory: (username) => + toResource( + injectQuery(() => { + const name = username() + return { + queryKey: ['username-availability', name], + enabled: !!name, + queryFn: (): Promise => + this.users.checkUsername(name!), + } + }), + ), + onSuccess: (result) => + result?.available + ? null + : { + kind: 'usernameTaken', + message: 'Username is already taken', + }, + onError: () => ({ + kind: 'usernameUnavailable', + message: 'Could not check username availability', + }), + }) + }) +} +``` + +Calling `reloadValidation()` on the field refetches the query only when its cached data is stale. + +## Comparison + +Choosing between Angular's built-in +[`resource`](https://angular.dev/guide/signals/resource) and TanStack Query depends on whether the +operation is isolated async state or server state shared across the application. + +This table focuses on built-in behavior and may not capture every custom implementation. Review +both APIs for the needs of your application. + +Feature/Capability Key: + +- ✅ 1st-class, built-in, and ready to use with no added configuration or code +- 🟡 Partial support +- 🟠 Supported through an additional package +- 🔶 Possible, but requires custom application code +- 🛑 Not built in + +| | Angular `resource` | TanStack Query | +| --------------------------------------- | ---------------------------------------------- | ----------------------------------------------------- | +| Reactive parameters and signal state | ✅ | ✅ | +| Request cancellation | ✅ | ✅ | +| Angular Resource interface | ✅ | ✅ Through `toResource(query)` | +| Shared cache by data identity | 🛑 | ✅ Query keys identify cached data | +| Request deduplication across components | 🛑 | ✅ For queries with the same key | +| Stale and garbage-collection timing | 🔶 | ✅ `staleTime` and `gcTime` | +| Cache invalidation and updates | 🔶 | ✅ `invalidateQueries` and `setQueryData` | +| Retries and background refetching | 🔶 | ✅ Including focus and reconnect refetching | +| Mutations and optimistic updates | 🔶 | ✅ `injectMutation` and QueryClient cache updates | +| SSR | ✅ A resource can transfer its value with `id` | ✅ The complete query cache is hydrated automatically | +| Persistence | 🔶 | 🟠 Through the persistence package | + +Angular `resource` is a good fit for a self-contained asynchronous task. It retains the value of +its own instance and can transfer that value during SSR, but it does not provide a shared, +query-keyed cache or coordinate invalidation and mutations across the application. Use TanStack +Query for server data that is reused, cached, invalidated, mutated, retried, or persisted. diff --git a/docs/framework/angular/typescript.md b/docs/framework/angular/typescript.md index 99781ffa50c..694be1f4cd8 100644 --- a/docs/framework/angular/typescript.md +++ b/docs/framework/angular/typescript.md @@ -6,12 +6,14 @@ replace: { 'useQuery': 'injectQuery', 'useMutation': 'injectMutation', - 'react-query': 'angular-query-experimental', - 'public API of React Query': 'public API of TanStack Query and - after the experimental phase, the angular-query package', + 'react-query': 'angular-query', + '@tanstack/angular-query': '@tanstack/angular-query', + 'public API of React Query': 'public API of TanStack Query and the Angular Query package', 'still follows': 'still follow', 'React Query': 'TanStack Query', '`success`': '`isSuccess()`', 'function:': 'function.', + "TanStack Query follows \\[DefinitelyTyped's support window\\]\\(https://github\\.com/DefinitelyTyped/DefinitelyTyped#support-window\\) and supports TypeScript versions released within the last 2 years\\. At the moment, that means TypeScript \\*\\*5\\.4\\*\\* and newer\\.": 'Angular Query supports the TypeScript versions required by your Angular version. See [Angular version compatibility](https://angular.dev/reference/versions).', } --- @@ -149,9 +151,9 @@ computed(() => { [//]: # 'RegisterErrorType' ```ts -import '@tanstack/angular-query-experimental' +import '@tanstack/angular-query' -declare module '@tanstack/angular-query-experimental' { +declare module '@tanstack/angular-query' { interface Register { // Use unknown so call sites must narrow explicitly. defaultError: unknown @@ -177,7 +179,7 @@ computed(() => { If you inline query options into `injectQuery`, you'll get automatic type inference. However, you might want to extract the query options into a separate function to share them between `injectQuery` and e.g. `queryClient.query`, or manage them in a service. In that case, you'd lose type inference. To get it back, you can use the `queryOptions` helper: ```ts -import { noop } from '@tanstack/angular-query-experimental' +import { noop } from '@tanstack/angular-query' @Injectable({ providedIn: 'root', diff --git a/docs/framework/angular/zoneless.md b/docs/framework/angular/zoneless.md deleted file mode 100644 index ee5811f1a86..00000000000 --- a/docs/framework/angular/zoneless.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: zoneless -title: Zoneless Angular ---- - -Because the Angular adapter for TanStack Query is built on signals, it fully supports Zoneless! - -Among Zoneless benefits are improved performance and debugging experience. For details see the [Angular documentation](https://angular.dev/guide/zoneless). - -> Besides Zoneless, ZoneJS change detection is also fully supported. - -> When using Zoneless, ensure you are on Angular v19 or later to take advantage of the `PendingTasks` integration that keeps `ApplicationRef.whenStable()` in sync with ongoing queries and mutations. diff --git a/examples/angular/auto-refetching/angular.json b/examples/angular/auto-refetching/angular.json index fb722b5a965..ac133cce756 100644 --- a/examples/angular/auto-refetching/angular.json +++ b/examples/angular/auto-refetching/angular.json @@ -82,6 +82,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, "configurations": { "production": { "buildTarget": "auto-refetching:build:production" diff --git a/examples/angular/auto-refetching/package.json b/examples/angular/auto-refetching/package.json index b195ec1653d..526a895de16 100644 --- a/examples/angular/auto-refetching/package.json +++ b/examples/angular/auto-refetching/package.json @@ -9,19 +9,20 @@ }, "private": true, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "5.8.3" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/examples/angular/auto-refetching/src/app/app.config.ts b/examples/angular/auto-refetching/src/app/app.config.ts index b9b2b6c36fa..ba6116f9f6b 100644 --- a/examples/angular/auto-refetching/src/app/app.config.ts +++ b/examples/angular/auto-refetching/src/app/app.config.ts @@ -3,11 +3,8 @@ import { withFetch, withInterceptors, } from '@angular/common/http' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' import { mockInterceptor } from './interceptor/mock-api.interceptor' import type { ApplicationConfig } from '@angular/core' @@ -15,13 +12,14 @@ export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withFetch(), withInterceptors([mockInterceptor])), provideTanStackQuery( - new QueryClient({ - defaultOptions: { - queries: { - gcTime: 1000 * 60 * 60 * 24, // 24 hours + () => + new QueryClient({ + defaultOptions: { + queries: { + gcTime: 1000 * 60 * 60 * 24, // 24 hours + }, }, - }, - }), + }), withDevtools(), ), ], diff --git a/examples/angular/auto-refetching/src/app/components/auto-refetching.component.ts b/examples/angular/auto-refetching/src/app/components/auto-refetching.component.ts index 00a0bdd022e..1838c357fd5 100644 --- a/examples/angular/auto-refetching/src/app/components/auto-refetching.component.ts +++ b/examples/angular/auto-refetching/src/app/components/auto-refetching.component.ts @@ -7,7 +7,7 @@ import { import { injectMutation, injectQuery, -} from '@tanstack/angular-query-experimental' +} from '@tanstack/angular-query' import { NgStyle } from '@angular/common' import { TasksService } from '../services/tasks.service' diff --git a/examples/angular/auto-refetching/src/app/services/tasks.service.ts b/examples/angular/auto-refetching/src/app/services/tasks.service.ts index 41d3dacb27d..a79bd5410fa 100644 --- a/examples/angular/auto-refetching/src/app/services/tasks.service.ts +++ b/examples/angular/auto-refetching/src/app/services/tasks.service.ts @@ -4,7 +4,7 @@ import { QueryClient, mutationOptions, queryOptions, -} from '@tanstack/angular-query-experimental' +} from '@tanstack/angular-query' import { lastValueFrom } from 'rxjs' diff --git a/examples/angular/basic-persister/angular.json b/examples/angular/basic-persister/angular.json index 64adfea7c48..9410e0f039f 100644 --- a/examples/angular/basic-persister/angular.json +++ b/examples/angular/basic-persister/angular.json @@ -82,6 +82,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, "configurations": { "production": { "buildTarget": "basic-persister:build:production" diff --git a/examples/angular/basic-persister/package.json b/examples/angular/basic-persister/package.json index 7552dfb951f..8e3d9443c4a 100644 --- a/examples/angular/basic-persister/package.json +++ b/examples/angular/basic-persister/package.json @@ -9,21 +9,22 @@ }, "private": true, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", - "@tanstack/angular-query-persist-client": "^5.103.2", - "@tanstack/query-async-storage-persister": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", + "@tanstack/angular-query-persist-client": "workspace:*", + "@tanstack/query-async-storage-persister": "^5.100.14", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "5.8.3" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/examples/angular/basic-persister/src/app/app.config.ts b/examples/angular/basic-persister/src/app/app.config.ts index ff5634cbb63..669064869ef 100644 --- a/examples/angular/basic-persister/src/app/app.config.ts +++ b/examples/angular/basic-persister/src/app/app.config.ts @@ -1,10 +1,7 @@ import { provideHttpClient, withFetch } from '@angular/common/http' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' import { withPersistQueryClient } from '@tanstack/angular-query-persist-client' -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { withDevtools } from '@tanstack/angular-query-devtools' import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister' import type { ApplicationConfig } from '@angular/core' @@ -16,20 +13,21 @@ export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withFetch()), provideTanStackQuery( - new QueryClient({ - defaultOptions: { - queries: { - staleTime: 1000 * 60, // 1 minute - gcTime: 1000 * 60 * 60 * 24, // 24 hours + () => + new QueryClient({ + defaultOptions: { + queries: { + staleTime: 1000 * 60, // 1 minute + gcTime: 1000 * 60 * 60 * 24, // 24 hours + }, }, - }, - }), + }), withDevtools(), - withPersistQueryClient({ + withPersistQueryClient(() => ({ persistOptions: { persister: localStoragePersister, }, - }), + })), ), ], } diff --git a/examples/angular/basic-persister/src/app/components/post.component.ts b/examples/angular/basic-persister/src/app/components/post.component.ts index 9eb32807db5..ff4c850b994 100644 --- a/examples/angular/basic-persister/src/app/components/post.component.ts +++ b/examples/angular/basic-persister/src/app/components/post.component.ts @@ -6,7 +6,7 @@ import { inject, input, } from '@angular/core' -import { QueryClient, injectQuery } from '@tanstack/angular-query-experimental' +import { QueryClient, injectQuery } from '@tanstack/angular-query' import { fromEvent, lastValueFrom, takeUntil } from 'rxjs' import { PostsService } from '../services/posts-service' diff --git a/examples/angular/basic-persister/src/app/components/posts.component.ts b/examples/angular/basic-persister/src/app/components/posts.component.ts index 2f04558e9d0..a3d62756cc8 100644 --- a/examples/angular/basic-persister/src/app/components/posts.component.ts +++ b/examples/angular/basic-persister/src/app/components/posts.component.ts @@ -5,7 +5,7 @@ import { Output, inject, } from '@angular/core' -import { QueryClient, injectQuery } from '@tanstack/angular-query-experimental' +import { QueryClient, injectQuery } from '@tanstack/angular-query' import { lastValueFrom } from 'rxjs' import { PostsService } from '../services/posts-service' diff --git a/examples/angular/basic/angular.json b/examples/angular/basic/angular.json index d6d3113a4df..6dae3a16eaf 100644 --- a/examples/angular/basic/angular.json +++ b/examples/angular/basic/angular.json @@ -82,6 +82,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, "configurations": { "production": { "buildTarget": "basic:build:production" diff --git a/examples/angular/basic/package.json b/examples/angular/basic/package.json index d626a68e05d..d874016e961 100644 --- a/examples/angular/basic/package.json +++ b/examples/angular/basic/package.json @@ -9,19 +9,20 @@ }, "private": true, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "5.8.3" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/examples/angular/basic/src/app/app.config.ts b/examples/angular/basic/src/app/app.config.ts index 77281147d1f..3c9a748815f 100644 --- a/examples/angular/basic/src/app/app.config.ts +++ b/examples/angular/basic/src/app/app.config.ts @@ -1,22 +1,20 @@ import { provideHttpClient, withFetch } from '@angular/common/http' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' import type { ApplicationConfig } from '@angular/core' export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withFetch()), provideTanStackQuery( - new QueryClient({ - defaultOptions: { - queries: { - gcTime: 1000 * 60 * 60 * 24, // 24 hours + () => + new QueryClient({ + defaultOptions: { + queries: { + gcTime: 1000 * 60 * 60 * 24, // 24 hours + }, }, - }, - }), + }), withDevtools(), ), ], diff --git a/examples/angular/basic/src/app/components/post.component.ts b/examples/angular/basic/src/app/components/post.component.ts index de80ffe6d36..27762afbb41 100644 --- a/examples/angular/basic/src/app/components/post.component.ts +++ b/examples/angular/basic/src/app/components/post.component.ts @@ -5,7 +5,7 @@ import { input, output, } from '@angular/core' -import { injectQuery } from '@tanstack/angular-query-experimental' +import { injectQuery } from '@tanstack/angular-query' import { fromEvent, lastValueFrom, takeUntil } from 'rxjs' import { PostsService } from '../services/posts-service' diff --git a/examples/angular/basic/src/app/components/posts.component.ts b/examples/angular/basic/src/app/components/posts.component.ts index c40010a8245..f585557b0bd 100644 --- a/examples/angular/basic/src/app/components/posts.component.ts +++ b/examples/angular/basic/src/app/components/posts.component.ts @@ -4,7 +4,7 @@ import { inject, output, } from '@angular/core' -import { QueryClient, injectQuery } from '@tanstack/angular-query-experimental' +import { QueryClient, injectQuery } from '@tanstack/angular-query' import { lastValueFrom } from 'rxjs' import { PostsService } from '../services/posts-service' diff --git a/examples/angular/devtools-panel/angular.json b/examples/angular/devtools-panel/angular.json index 1db304e1dbc..a7dcb1397af 100644 --- a/examples/angular/devtools-panel/angular.json +++ b/examples/angular/devtools-panel/angular.json @@ -80,6 +80,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, "configurations": { "production": { "buildTarget": "devtools-panel:build:production" diff --git a/examples/angular/devtools-panel/package.json b/examples/angular/devtools-panel/package.json index 1e89d6cc584..016575928a6 100644 --- a/examples/angular/devtools-panel/package.json +++ b/examples/angular/devtools-panel/package.json @@ -9,20 +9,21 @@ }, "private": true, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@angular/router": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@angular/router": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "5.8.3" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/examples/angular/devtools-panel/src/app/app.config.ts b/examples/angular/devtools-panel/src/app/app.config.ts index b51d14cb81e..68222c873ee 100644 --- a/examples/angular/devtools-panel/src/app/app.config.ts +++ b/examples/angular/devtools-panel/src/app/app.config.ts @@ -1,10 +1,7 @@ import { provideHttpClient, withFetch } from '@angular/common/http' import { provideRouter } from '@angular/router' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' import { routes } from './app.routes' import type { ApplicationConfig } from '@angular/core' @@ -12,6 +9,6 @@ export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withFetch()), provideRouter(routes), - provideTanStackQuery(new QueryClient()), + provideTanStackQuery(() => new QueryClient()), ], } diff --git a/examples/angular/devtools-panel/src/app/components/basic-devtools-panel-example.component.ts b/examples/angular/devtools-panel/src/app/components/basic-devtools-panel-example.component.ts index f0a56611eb0..8f3801c52d8 100644 --- a/examples/angular/devtools-panel/src/app/components/basic-devtools-panel-example.component.ts +++ b/examples/angular/devtools-panel/src/app/components/basic-devtools-panel-example.component.ts @@ -4,7 +4,7 @@ import { signal, viewChild, } from '@angular/core' -import { injectDevtoolsPanel } from '@tanstack/angular-query-experimental/devtools-panel' +import { injectDevtoolsPanel } from '@tanstack/angular-query-devtools/devtools-panel' import { ExampleQueryComponent } from './example-query.component' import type { ElementRef } from '@angular/core' diff --git a/examples/angular/devtools-panel/src/app/components/example-query.component.ts b/examples/angular/devtools-panel/src/app/components/example-query.component.ts index 1537167a948..c8ce491e990 100644 --- a/examples/angular/devtools-panel/src/app/components/example-query.component.ts +++ b/examples/angular/devtools-panel/src/app/components/example-query.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core' -import { injectQuery } from '@tanstack/angular-query-experimental' +import { injectQuery } from '@tanstack/angular-query' import { HttpClient } from '@angular/common/http' import { lastValueFrom } from 'rxjs' diff --git a/examples/angular/devtools-panel/src/app/components/lazy-load-devtools-panel-example.component.ts b/examples/angular/devtools-panel/src/app/components/lazy-load-devtools-panel-example.component.ts index 9bb23b11924..47c8192d9b4 100644 --- a/examples/angular/devtools-panel/src/app/components/lazy-load-devtools-panel-example.component.ts +++ b/examples/angular/devtools-panel/src/app/components/lazy-load-devtools-panel-example.component.ts @@ -5,12 +5,13 @@ import { computed, effect, inject, + runInInjectionContext, signal, viewChild, } from '@angular/core' import { ExampleQueryComponent } from './example-query.component' import type { ElementRef } from '@angular/core' -import type { DevtoolsPanelRef } from '@tanstack/angular-query-experimental/devtools-panel' +import type { DevtoolsPanelRef } from '@tanstack/angular-query-devtools/devtools-panel' @Component({ selector: 'lazy-load-devtools-panel-example', @@ -49,11 +50,11 @@ export default class LazyLoadDevtoolsPanelExampleComponent { if (this.devtools()) return if (this.isOpen()) { this.devtools.set( - import('@tanstack/angular-query-experimental/devtools-panel').then( + import('@tanstack/angular-query-devtools/devtools-panel').then( ({ injectDevtoolsPanel }) => - injectDevtoolsPanel(this.devToolsOptions, { - injector: this.injector, - }), + runInInjectionContext(this.injector, () => + injectDevtoolsPanel(this.devToolsOptions), + ), ), ) } diff --git a/examples/angular/dynamic-devtools/.devcontainer/devcontainer.json b/examples/angular/dynamic-devtools/.devcontainer/devcontainer.json new file mode 100644 index 00000000000..365adf8f4c3 --- /dev/null +++ b/examples/angular/dynamic-devtools/.devcontainer/devcontainer.json @@ -0,0 +1,4 @@ +{ + "name": "Node.js", + "image": "mcr.microsoft.com/devcontainers/javascript-node:22" +} diff --git a/examples/angular/dynamic-devtools/.eslintrc.cjs b/examples/angular/dynamic-devtools/.eslintrc.cjs new file mode 100644 index 00000000000..cca134ce166 --- /dev/null +++ b/examples/angular/dynamic-devtools/.eslintrc.cjs @@ -0,0 +1,6 @@ +// @ts-check + +/** @type {import('eslint').Linter.Config} */ +const config = {} + +module.exports = config diff --git a/examples/angular/dynamic-devtools/README.md b/examples/angular/dynamic-devtools/README.md new file mode 100644 index 00000000000..fab7a9d9df2 --- /dev/null +++ b/examples/angular/dynamic-devtools/README.md @@ -0,0 +1,10 @@ +# TanStack Query Angular dynamic devtools example + +Devtools load automatically in development. In production builds, press **⌘ Ctrl Shift D** (macOS) to load them on demand. + +To run: + +- From the repo root: `pnpm install` then `pnpm --filter @tanstack/query-example-angular-dynamic-devtools start` +- From this folder: `pnpm start` + +For a production-like devserver (so you can try the shortcut), use `ng serve --configuration production`. diff --git a/examples/angular/dynamic-devtools/angular.json b/examples/angular/dynamic-devtools/angular.json new file mode 100644 index 00000000000..16d6a1b3a26 --- /dev/null +++ b/examples/angular/dynamic-devtools/angular.json @@ -0,0 +1,133 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "cli": { + "packageManager": "pnpm", + "analytics": false, + "cache": { + "enabled": false + } + }, + "newProjectRoot": "projects", + "projects": { + "dynamic-devtools": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "inlineTemplate": true, + "inlineStyle": true, + "skipTests": true + }, + "@schematics/angular:class": { + "skipTests": true + }, + "@schematics/angular:directive": { + "skipTests": true + }, + "@schematics/angular:guard": { + "skipTests": true + }, + "@schematics/angular:interceptor": { + "skipTests": true + }, + "@schematics/angular:pipe": { + "skipTests": true + }, + "@schematics/angular:resolver": { + "skipTests": true + }, + "@schematics/angular:service": { + "skipTests": true + } + }, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular/build:application", + "options": { + "outputPath": "dist/dynamic-devtools", + "index": "src/index.html", + "browser": "src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "tsconfig.app.json", + "assets": ["src/favicon.ico"], + "styles": ["src/styles.css"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, + "configurations": { + "production": { + "buildTarget": "dynamic-devtools:build:production" + }, + "development": { + "buildTarget": "dynamic-devtools:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular/build:extract-i18n", + "options": { + "buildTarget": "dynamic-devtools:build" + } + } + } + } + }, + "schematics": { + "@schematics/angular:component": { + "type": "component" + }, + "@schematics/angular:directive": { + "type": "directive" + }, + "@schematics/angular:service": { + "type": "service" + }, + "@schematics/angular:guard": { + "typeSeparator": "." + }, + "@schematics/angular:interceptor": { + "typeSeparator": "." + }, + "@schematics/angular:module": { + "typeSeparator": "." + }, + "@schematics/angular:pipe": { + "typeSeparator": "." + }, + "@schematics/angular:resolver": { + "typeSeparator": "." + } + } +} diff --git a/examples/angular/dynamic-devtools/package.json b/examples/angular/dynamic-devtools/package.json new file mode 100644 index 00000000000..d2080678fe4 --- /dev/null +++ b/examples/angular/dynamic-devtools/package.json @@ -0,0 +1,28 @@ +{ + "name": "@tanstack/query-example-angular-dynamic-devtools", + "type": "module", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development" + }, + "private": true, + "dependencies": { + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", + "rxjs": "^7.8.2", + "tslib": "^2.8.1", + "zone.js": "0.16.1" + }, + "devDependencies": { + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" + } +} diff --git a/examples/angular/dynamic-devtools/src/app/app.component.ts b/examples/angular/dynamic-devtools/src/app/app.component.ts new file mode 100644 index 00000000000..4f389242fb8 --- /dev/null +++ b/examples/angular/dynamic-devtools/src/app/app.component.ts @@ -0,0 +1,10 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core' +import { DynamicDevtoolsExampleComponent } from './components/dynamic-devtools-example.component' + +@Component({ + selector: 'app-root', + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [DynamicDevtoolsExampleComponent], + template: ``, +}) +export class AppComponent {} diff --git a/examples/angular/dynamic-devtools/src/app/app.config.ts b/examples/angular/dynamic-devtools/src/app/app.config.ts new file mode 100644 index 00000000000..30f1915f6aa --- /dev/null +++ b/examples/angular/dynamic-devtools/src/app/app.config.ts @@ -0,0 +1,18 @@ +import { provideHttpClient, withFetch } from '@angular/common/http' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools/production' +import { inject } from '@angular/core' +import type { ApplicationConfig } from '@angular/core' +import { DevtoolsOptionsManager } from './devtools-options.manager' + +export const appConfig: ApplicationConfig = { + providers: [ + provideHttpClient(withFetch()), + provideTanStackQuery( + () => new QueryClient(), + withDevtools(() => ({ + loadDevtools: inject(DevtoolsOptionsManager).loadDevtools, + })), + ), + ], +} diff --git a/examples/angular/dynamic-devtools/src/app/components/dynamic-devtools-example.component.html b/examples/angular/dynamic-devtools/src/app/components/dynamic-devtools-example.component.html new file mode 100644 index 00000000000..9d68159ed16 --- /dev/null +++ b/examples/angular/dynamic-devtools/src/app/components/dynamic-devtools-example.component.html @@ -0,0 +1,18 @@ +

+ Devtools load in development automatically. For a production build, press + CtrlShiftD once to load them. +

+ +@if (query.isPending()) { +
Loading...
+} +@if (query.isError()) { +
An error has occurred: {{ query.error().message }}
+} +@if (query.data(); as data) { +

{{ data.name }}

+

{{ data.description }}

+ 👀 {{ data.subscribers_count }} + ✨ {{ data.stargazers_count }} + 🍴 {{ data.forks_count }} +} diff --git a/examples/angular/dynamic-devtools/src/app/components/dynamic-devtools-example.component.ts b/examples/angular/dynamic-devtools/src/app/components/dynamic-devtools-example.component.ts new file mode 100644 index 00000000000..e810f3ec773 --- /dev/null +++ b/examples/angular/dynamic-devtools/src/app/components/dynamic-devtools-example.component.ts @@ -0,0 +1,29 @@ +import { HttpClient } from '@angular/common/http' +import { ChangeDetectionStrategy, Component, inject } from '@angular/core' +import { injectQuery } from '@tanstack/angular-query' +import { lastValueFrom } from 'rxjs' + +interface Response { + name: string + description: string + subscribers_count: number + stargazers_count: number + forks_count: number +} + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'dynamic-devtools-example', + templateUrl: './dynamic-devtools-example.component.html', +}) +export class DynamicDevtoolsExampleComponent { + readonly #http = inject(HttpClient) + + readonly query = injectQuery(() => ({ + queryKey: ['repoData'], + queryFn: () => + lastValueFrom( + this.#http.get('https://api.github.com/repos/tanstack/query'), + ), + })) +} diff --git a/examples/angular/dynamic-devtools/src/app/devtools-options.manager.ts b/examples/angular/dynamic-devtools/src/app/devtools-options.manager.ts new file mode 100644 index 00000000000..23525f841ac --- /dev/null +++ b/examples/angular/dynamic-devtools/src/app/devtools-options.manager.ts @@ -0,0 +1,19 @@ +import { Injectable, isDevMode } from '@angular/core' +import { toSignal } from '@angular/core/rxjs-interop' +import { fromEvent, map, scan } from 'rxjs' + +@Injectable({ providedIn: 'root' }) +export class DevtoolsOptionsManager { + readonly loadDevtools = toSignal( + fromEvent(document, 'keydown').pipe( + map( + (event): boolean => + event.metaKey && event.ctrlKey && event.shiftKey && event.key === 'D', + ), + scan((acc, curr) => acc || curr, false), + ), + { + initialValue: false, + }, + ) +} diff --git a/examples/angular/dynamic-devtools/src/favicon.ico b/examples/angular/dynamic-devtools/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..57614f9c967596fad0a3989bec2b1deff33034f6 GIT binary patch literal 15086 zcmd^G33O9Omi+`8$@{|M-I6TH3wzF-p5CV8o}7f~KxR60LK+ApEFB<$bcciv%@SmA zV{n>g85YMFFeU*Uvl=i4v)C*qgnb;$GQ=3XTe9{Y%c`mO%su)noNCCQ*@t1WXn|B(hQ7i~ zrUK8|pUkD6#lNo!bt$6)jR!&C?`P5G(`e((P($RaLeq+o0Vd~f11;qB05kdbAOm?r zXv~GYr_sibQO9NGTCdT;+G(!{4Xs@4fPak8#L8PjgJwcs-Mm#nR_Z0s&u?nDX5^~@ z+A6?}g0|=4e_LoE69pPFO`yCD@BCjgKpzMH0O4Xs{Ahc?K3HC5;l=f zg>}alhBXX&);z$E-wai+9TTRtBX-bWYY@cl$@YN#gMd~tM_5lj6W%8ah4;uZ;jP@Q zVbuel1rPA?2@x9Y+u?e`l{Z4ngfG5q5BLH5QsEu4GVpt{KIp1?U)=3+KQ;%7ec8l* zdV=zZgN5>O3G(3L2fqj3;oBbZZw$Ij@`Juz@?+yy#OPw)>#wsTewVgTK9BGt5AbZ&?K&B3GVF&yu?@(Xj3fR3n+ZP0%+wo)D9_xp>Z$`A4 zfV>}NWjO#3lqumR0`gvnffd9Ka}JJMuHS&|55-*mCD#8e^anA<+sFZVaJe7{=p*oX zE_Uv?1>e~ga=seYzh{9P+n5<+7&9}&(kwqSaz;1aD|YM3HBiy<))4~QJSIryyqp| z8nGc(8>3(_nEI4n)n7j(&d4idW1tVLjZ7QbNLXg;LB ziHsS5pXHEjGJZb59KcvS~wv;uZR-+4qEqow`;JCfB*+b^UL^3!?;-^F%yt=VjU|v z39SSqKcRu_NVvz!zJzL0CceJaS6%!(eMshPv_0U5G`~!a#I$qI5Ic(>IONej@aH=f z)($TAT#1I{iCS4f{D2+ApS=$3E7}5=+y(rA9mM#;Cky%b*Gi0KfFA`ofKTzu`AV-9 znW|y@19rrZ*!N2AvDi<_ZeR3O2R{#dh1#3-d%$k${Rx42h+i&GZo5!C^dSL34*AKp z27mTd>k>?V&X;Nl%GZ(>0s`1UN~Hfyj>KPjtnc|)xM@{H_B9rNr~LuH`Gr5_am&Ep zTjZA8hljNj5H1Ipm-uD9rC}U{-vR!eay5&6x6FkfupdpT*84MVwGpdd(}ib)zZ3Ky z7C$pnjc82(W_y_F{PhYj?o!@3__UUvpX)v69aBSzYj3 zdi}YQkKs^SyXyFG2LTRz9{(w}y~!`{EuAaUr6G1M{*%c+kP1olW9z23dSH!G4_HSK zzae-DF$OGR{ofP*!$a(r^5Go>I3SObVI6FLY)N@o<*gl0&kLo-OT{Tl*7nCz>Iq=? zcigIDHtj|H;6sR?or8Wd_a4996GI*CXGU}o;D9`^FM!AT1pBY~?|4h^61BY#_yIfO zKO?E0 zJ{Pc`9rVEI&$xxXu`<5E)&+m(7zX^v0rqofLs&bnQT(1baQkAr^kEsk)15vlzAZ-l z@OO9RF<+IiJ*O@HE256gCt!bF=NM*vh|WVWmjVawcNoksRTMvR03H{p@cjwKh(CL4 z7_PB(dM=kO)!s4fW!1p0f93YN@?ZSG` z$B!JaAJCtW$B97}HNO9(x-t30&E}Mo1UPi@Av%uHj~?T|!4JLwV;KCx8xO#b9IlUW zI6+{a@Wj|<2Y=U;a@vXbxqZNngH8^}LleE_4*0&O7#3iGxfJ%Id>+sb;7{L=aIic8 z|EW|{{S)J-wr@;3PmlxRXU8!e2gm_%s|ReH!reFcY8%$Hl4M5>;6^UDUUae?kOy#h zk~6Ee_@ZAn48Bab__^bNmQ~+k=02jz)e0d9Z3>G?RGG!65?d1>9}7iG17?P*=GUV-#SbLRw)Hu{zx*azHxWkGNTWl@HeWjA?39Ia|sCi{e;!^`1Oec zb>Z|b65OM*;eC=ZLSy?_fg$&^2xI>qSLA2G*$nA3GEnp3$N-)46`|36m*sc#4%C|h zBN<2U;7k>&G_wL4=Ve5z`ubVD&*Hxi)r@{4RCDw7U_D`lbC(9&pG5C*z#W>8>HU)h z!h3g?2UL&sS!oY5$3?VlA0Me9W5e~V;2jds*fz^updz#AJ%G8w2V}AEE?E^=MK%Xt z__Bx1cr7+DQmuHmzn*|hh%~eEc9@m05@clWfpEFcr+06%0&dZJH&@8^&@*$qR@}o3 z@Tuuh2FsLz^zH+dN&T&?0G3I?MpmYJ;GP$J!EzjeM#YLJ!W$}MVNb0^HfOA>5Fe~UNn%Zk(PT@~9}1dt)1UQ zU*B5K?Dl#G74qmg|2>^>0WtLX#Jz{lO4NT`NYB*(L#D|5IpXr9v&7a@YsGp3vLR7L zHYGHZg7{ie6n~2p$6Yz>=^cEg7tEgk-1YRl%-s7^cbqFb(U7&Dp78+&ut5!Tn(hER z|Gp4Ed@CnOPeAe|N>U(dB;SZ?NU^AzoD^UAH_vamp6Ws}{|mSq`^+VP1g~2B{%N-!mWz<`)G)>V-<`9`L4?3dM%Qh6<@kba+m`JS{Ya@9Fq*m6$$ zA1%Ogc~VRH33|S9l%CNb4zM%k^EIpqY}@h{w(aBcJ9c05oiZx#SK9t->5lSI`=&l~ z+-Ic)a{FbBhXV$Xt!WRd`R#Jk-$+_Z52rS>?Vpt2IK<84|E-SBEoIw>cs=a{BlQ7O z-?{Fy_M&84&9|KM5wt~)*!~i~E=(6m8(uCO)I=)M?)&sRbzH$9Rovzd?ZEY}GqX+~ zFbEbLz`BZ49=2Yh-|<`waK-_4!7`ro@zlC|r&I4fc4oyb+m=|c8)8%tZ-z5FwhzDt zL5kB@u53`d@%nHl0Sp)Dw`(QU&>vujEn?GPEXUW!Wi<+4e%BORl&BIH+SwRcbS}X@ z01Pk|vA%OdJKAs17zSXtO55k!;%m9>1eW9LnyAX4uj7@${O6cfii`49qTNItzny5J zH&Gj`e}o}?xjQ}r?LrI%FjUd@xflT3|7LA|ka%Q3i}a8gVm<`HIWoJGH=$EGClX^C0lysQJ>UO(q&;`T#8txuoQ_{l^kEV9CAdXuU1Ghg8 zN_6hHFuy&1x24q5-(Z7;!poYdt*`UTdrQOIQ!2O7_+AHV2hgXaEz7)>$LEdG z<8vE^Tw$|YwZHZDPM!SNOAWG$?J)MdmEk{U!!$M#fp7*Wo}jJ$Q(=8>R`Ats?e|VU?Zt7Cdh%AdnfyN3MBWw{ z$OnREvPf7%z6`#2##_7id|H%Y{vV^vWXb?5d5?a_y&t3@p9t$ncHj-NBdo&X{wrfJ zamN)VMYROYh_SvjJ=Xd!Ga?PY_$;*L=SxFte!4O6%0HEh%iZ4=gvns7IWIyJHa|hT z2;1+e)`TvbNb3-0z&DD_)Jomsg-7p_Uh`wjGnU1urmv1_oVqRg#=C?e?!7DgtqojU zWoAB($&53;TsXu^@2;8M`#z{=rPy?JqgYM0CDf4v@z=ZD|ItJ&8%_7A#K?S{wjxgd z?xA6JdJojrWpB7fr2p_MSsU4(R7=XGS0+Eg#xR=j>`H@R9{XjwBmqAiOxOL` zt?XK-iTEOWV}f>Pz3H-s*>W z4~8C&Xq25UQ^xH6H9kY_RM1$ch+%YLF72AA7^b{~VNTG}Tj#qZltz5Q=qxR`&oIlW Nr__JTFzvMr^FKp4S3v*( literal 0 HcmV?d00001 diff --git a/examples/angular/dynamic-devtools/src/index.html b/examples/angular/dynamic-devtools/src/index.html new file mode 100644 index 00000000000..9988a64448b --- /dev/null +++ b/examples/angular/dynamic-devtools/src/index.html @@ -0,0 +1,13 @@ + + + + + TanStack Query Angular dynamic devtools example + + + + + + + + diff --git a/examples/angular/dynamic-devtools/src/main.ts b/examples/angular/dynamic-devtools/src/main.ts new file mode 100644 index 00000000000..c3d8f9af997 --- /dev/null +++ b/examples/angular/dynamic-devtools/src/main.ts @@ -0,0 +1,5 @@ +import { bootstrapApplication } from '@angular/platform-browser' +import { appConfig } from './app/app.config' +import { AppComponent } from './app/app.component' + +bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err)) diff --git a/examples/angular/dynamic-devtools/src/styles.css b/examples/angular/dynamic-devtools/src/styles.css new file mode 100644 index 00000000000..256d518a5e1 --- /dev/null +++ b/examples/angular/dynamic-devtools/src/styles.css @@ -0,0 +1,18 @@ +/* You can add global styles to this file, and also import other style files */ + +.hint { + font-size: 0.9rem; + color: #444; + max-width: 42rem; + line-height: 1.45; +} + +kbd { + display: inline-block; + padding: 0.1rem 0.35rem; + margin: 0 0.1rem; + font-size: 0.8rem; + border: 1px solid #ccc; + border-radius: 3px; + background: #f7f7f7; +} diff --git a/examples/angular/dynamic-devtools/tsconfig.app.json b/examples/angular/dynamic-devtools/tsconfig.app.json new file mode 100644 index 00000000000..5b9d3c5ecb0 --- /dev/null +++ b/examples/angular/dynamic-devtools/tsconfig.app.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"] +} diff --git a/examples/angular/dynamic-devtools/tsconfig.json b/examples/angular/dynamic-devtools/tsconfig.json new file mode 100644 index 00000000000..44e0a5238b1 --- /dev/null +++ b/examples/angular/dynamic-devtools/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "isolatedModules": true, + "esModuleInterop": true, + "sourceMap": true, + "declaration": false, + "experimentalDecorators": true, + "moduleResolution": "Bundler", + "importHelpers": true, + "target": "ES2022", + "module": "ES2022", + "useDefineForClassFields": false, + "lib": ["ES2022", "dom"] + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictStandalone": true, + "strictTemplates": true + } +} diff --git a/examples/angular/dynamic-queries/README.md b/examples/angular/dynamic-queries/README.md new file mode 100644 index 00000000000..b2e897b81b7 --- /dev/null +++ b/examples/angular/dynamic-queries/README.md @@ -0,0 +1,10 @@ +# TanStack Query Angular dynamic queries example + +This example keeps a list of items in an Angular signal and creates one +`injectQueries` entry for each item. Add and remove items to see the query list +and its rendered results update together. + +To run this example: + +- `pnpm install` +- `pnpm start` diff --git a/examples/angular/dynamic-queries/angular.json b/examples/angular/dynamic-queries/angular.json new file mode 100644 index 00000000000..7db4b2559d3 --- /dev/null +++ b/examples/angular/dynamic-queries/angular.json @@ -0,0 +1,49 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "cli": { "packageManager": "pnpm", "analytics": false }, + "projects": { + "dynamic-queries": { + "projectType": "application", + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular/build:application", + "options": { + "outputPath": "dist/dynamic-queries", + "index": "src/index.html", + "browser": "src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "tsconfig.app.json", + "assets": [], + "styles": ["src/styles.css"] + }, + "configurations": { + "production": { "outputHashing": "all" }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, + "configurations": { + "production": { "buildTarget": "dynamic-queries:build:production" }, + "development": { + "buildTarget": "dynamic-queries:build:development" + } + }, + "defaultConfiguration": "development" + } + } + } + } +} diff --git a/examples/angular/dynamic-queries/package.json b/examples/angular/dynamic-queries/package.json new file mode 100644 index 00000000000..757335c5767 --- /dev/null +++ b/examples/angular/dynamic-queries/package.json @@ -0,0 +1,28 @@ +{ + "name": "@tanstack/query-example-angular-dynamic-queries", + "private": true, + "type": "module", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development" + }, + "dependencies": { + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", + "rxjs": "^7.8.2", + "tslib": "^2.8.1", + "zone.js": "0.16.1" + }, + "devDependencies": { + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" + } +} diff --git a/examples/angular/dynamic-queries/src/app/app.component.ts b/examples/angular/dynamic-queries/src/app/app.component.ts new file mode 100644 index 00000000000..f3cc5ecd8d4 --- /dev/null +++ b/examples/angular/dynamic-queries/src/app/app.component.ts @@ -0,0 +1,107 @@ +import { ChangeDetectionStrategy, Component, signal } from '@angular/core' +import { injectQueries } from '@tanstack/angular-query' + +type Item = { + id: number + name: string +} + +type ItemDetails = { + description: string + updatedAt: string +} + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'app-root', + template: ` +
+

Dynamic queries

+

+ Each item below owns one entry in injectQueries. Add or + remove items to change the query list. +

+ + + + @if (items().length === 0) { +

No items. Add one to start a query.

+ } @else { +
    + @for (item of items(); track item.id; let index = $index) { +
  • +
    + {{ item.name }} + @if (queries()[index].isPending()) { + Loading... + } @else if (queries()[index].isError()) { + Could not load this item. + } @else { + {{ queries()[index].data()?.description }} + } +
    + +
  • + } +
+ } +
+ `, + styles: ` + main { + font: + 16px/1.5 system-ui, + sans-serif; + margin: 3rem auto; + max-width: 42rem; + padding: 0 1rem; + } + + button { + cursor: pointer; + margin: 0.25rem; + padding: 0.45rem 0.7rem; + } + + li { + align-items: center; + display: flex; + justify-content: space-between; + margin: 0.75rem 0; + } + `, +}) +export class AppComponent { + readonly items = signal>([ + { id: 1, name: 'First item' }, + { id: 2, name: 'Second item' }, + ]) + + readonly queries = injectQueries(() => ({ + queries: this.items().map((item) => ({ + queryKey: ['item-details', item.id], + queryFn: () => this.loadItemDetails(item), + })), + })) + + #nextId = 3 + + addItem(): void { + const id = this.#nextId++ + this.items.update((items) => [...items, { id, name: `Item ${id}` }]) + } + + removeItem(id: number): void { + this.items.update((items) => items.filter((item) => item.id !== id)) + } + + private async loadItemDetails(item: Item): Promise { + await new Promise((resolve) => setTimeout(resolve, 350)) + return { + description: `${item.name} was loaded by its own query.`, + updatedAt: new Date().toLocaleTimeString(), + } + } +} diff --git a/examples/angular/dynamic-queries/src/app/app.config.ts b/examples/angular/dynamic-queries/src/app/app.config.ts new file mode 100644 index 00000000000..0038688124f --- /dev/null +++ b/examples/angular/dynamic-queries/src/app/app.config.ts @@ -0,0 +1,7 @@ +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' +import type { ApplicationConfig } from '@angular/core' + +export const appConfig: ApplicationConfig = { + providers: [provideTanStackQuery(() => new QueryClient(), withDevtools())], +} diff --git a/examples/angular/dynamic-queries/src/index.html b/examples/angular/dynamic-queries/src/index.html new file mode 100644 index 00000000000..cf7c7b4728d --- /dev/null +++ b/examples/angular/dynamic-queries/src/index.html @@ -0,0 +1,12 @@ + + + + + Dynamic Angular queries + + + + + + + diff --git a/examples/angular/dynamic-queries/src/main.ts b/examples/angular/dynamic-queries/src/main.ts new file mode 100644 index 00000000000..ef15666eff7 --- /dev/null +++ b/examples/angular/dynamic-queries/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser' +import { appConfig } from './app/app.config' +import { AppComponent } from './app/app.component' + +bootstrapApplication(AppComponent, appConfig).catch((error) => + console.error(error), +) diff --git a/examples/angular/dynamic-queries/src/styles.css b/examples/angular/dynamic-queries/src/styles.css new file mode 100644 index 00000000000..acd67bf82bc --- /dev/null +++ b/examples/angular/dynamic-queries/src/styles.css @@ -0,0 +1,5 @@ +body { + background: #f7f7f8; + color: #202124; + margin: 0; +} diff --git a/examples/angular/dynamic-queries/tsconfig.app.json b/examples/angular/dynamic-queries/tsconfig.app.json new file mode 100644 index 00000000000..a7da28e8cea --- /dev/null +++ b/examples/angular/dynamic-queries/tsconfig.app.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { "outDir": "./out-tsc/app", "types": [] }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"] +} diff --git a/examples/angular/dynamic-queries/tsconfig.json b/examples/angular/dynamic-queries/tsconfig.json new file mode 100644 index 00000000000..f42b458e4ac --- /dev/null +++ b/examples/angular/dynamic-queries/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "isolatedModules": true, + "experimentalDecorators": true, + "moduleResolution": "bundler", + "importHelpers": true, + "target": "ES2022", + "module": "preserve", + "lib": ["ES2022", "dom"] + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/examples/angular/infinite-query-with-max-pages/angular.json b/examples/angular/infinite-query-with-max-pages/angular.json index 702c1da4eda..53d8e9c61c8 100644 --- a/examples/angular/infinite-query-with-max-pages/angular.json +++ b/examples/angular/infinite-query-with-max-pages/angular.json @@ -82,6 +82,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, "configurations": { "production": { "buildTarget": "infinite-query-with-max-pages:build:production" diff --git a/examples/angular/infinite-query-with-max-pages/package.json b/examples/angular/infinite-query-with-max-pages/package.json index b7db387ea6b..69eeb135e3b 100644 --- a/examples/angular/infinite-query-with-max-pages/package.json +++ b/examples/angular/infinite-query-with-max-pages/package.json @@ -9,19 +9,20 @@ "watch": "ng build --watch --configuration development" }, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "5.8.3" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/examples/angular/infinite-query-with-max-pages/src/app/app.config.ts b/examples/angular/infinite-query-with-max-pages/src/app/app.config.ts index 06854c4a7d4..87870fdbbb2 100644 --- a/examples/angular/infinite-query-with-max-pages/src/app/app.config.ts +++ b/examples/angular/infinite-query-with-max-pages/src/app/app.config.ts @@ -3,11 +3,8 @@ import { withFetch, withInterceptors, } from '@angular/common/http' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' import { projectsMockInterceptor } from './api/projects-mock.interceptor' import type { ApplicationConfig } from '@angular/core' @@ -15,13 +12,14 @@ export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withInterceptors([projectsMockInterceptor]), withFetch()), provideTanStackQuery( - new QueryClient({ - defaultOptions: { - queries: { - gcTime: 1000 * 60 * 60 * 24, // 24 hours + () => + new QueryClient({ + defaultOptions: { + queries: { + gcTime: 1000 * 60 * 60 * 24, // 24 hours + }, }, - }, - }), + }), withDevtools(), ), ], diff --git a/examples/angular/infinite-query-with-max-pages/src/app/components/example.component.ts b/examples/angular/infinite-query-with-max-pages/src/app/components/example.component.ts index 71c141e3e46..d9d04cc9f24 100644 --- a/examples/angular/infinite-query-with-max-pages/src/app/components/example.component.ts +++ b/examples/angular/infinite-query-with-max-pages/src/app/components/example.component.ts @@ -4,7 +4,7 @@ import { computed, inject, } from '@angular/core' -import { injectInfiniteQuery } from '@tanstack/angular-query-experimental' +import { injectInfiniteQuery } from '@tanstack/angular-query' import { lastValueFrom } from 'rxjs' import { ProjectStyleDirective } from '../directives/project-style.directive' import { ProjectsService } from '../services/projects.service' diff --git a/examples/angular/optimistic-updates/angular.json b/examples/angular/optimistic-updates/angular.json index 7051bc8815e..47e04f26d66 100644 --- a/examples/angular/optimistic-updates/angular.json +++ b/examples/angular/optimistic-updates/angular.json @@ -82,6 +82,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, "configurations": { "production": { "buildTarget": "optimistic-updates:build:production" diff --git a/examples/angular/optimistic-updates/package.json b/examples/angular/optimistic-updates/package.json index a579fc35d4c..7192e04c8f8 100644 --- a/examples/angular/optimistic-updates/package.json +++ b/examples/angular/optimistic-updates/package.json @@ -9,20 +9,21 @@ }, "private": true, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/forms": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/forms": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "5.8.3" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/examples/angular/optimistic-updates/src/app/app.config.ts b/examples/angular/optimistic-updates/src/app/app.config.ts index b9b2b6c36fa..ba6116f9f6b 100644 --- a/examples/angular/optimistic-updates/src/app/app.config.ts +++ b/examples/angular/optimistic-updates/src/app/app.config.ts @@ -3,11 +3,8 @@ import { withFetch, withInterceptors, } from '@angular/common/http' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' import { mockInterceptor } from './interceptor/mock-api.interceptor' import type { ApplicationConfig } from '@angular/core' @@ -15,13 +12,14 @@ export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withFetch(), withInterceptors([mockInterceptor])), provideTanStackQuery( - new QueryClient({ - defaultOptions: { - queries: { - gcTime: 1000 * 60 * 60 * 24, // 24 hours + () => + new QueryClient({ + defaultOptions: { + queries: { + gcTime: 1000 * 60 * 60 * 24, // 24 hours + }, }, - }, - }), + }), withDevtools(), ), ], diff --git a/examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts b/examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts index 2b0b4cc1c4f..cbb01f0c0d5 100644 --- a/examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts +++ b/examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts @@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core' import { injectMutation, injectQuery, -} from '@tanstack/angular-query-experimental' +} from '@tanstack/angular-query' import { FormsModule } from '@angular/forms' import { DatePipe } from '@angular/common' import { TasksService } from '../services/tasks.service' diff --git a/examples/angular/optimistic-updates/src/app/services/tasks.service.ts b/examples/angular/optimistic-updates/src/app/services/tasks.service.ts index d9a2d62428d..2da0dee782c 100644 --- a/examples/angular/optimistic-updates/src/app/services/tasks.service.ts +++ b/examples/angular/optimistic-updates/src/app/services/tasks.service.ts @@ -4,7 +4,7 @@ import { QueryClient, mutationOptions, queryOptions, -} from '@tanstack/angular-query-experimental' +} from '@tanstack/angular-query' import { lastValueFrom } from 'rxjs' diff --git a/examples/angular/pagination/angular.json b/examples/angular/pagination/angular.json index 222be20143e..5f1e19ba0db 100644 --- a/examples/angular/pagination/angular.json +++ b/examples/angular/pagination/angular.json @@ -82,6 +82,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, "configurations": { "production": { "buildTarget": "pagination:build:production" diff --git a/examples/angular/pagination/package.json b/examples/angular/pagination/package.json index 5edc7a6b25b..57e6dcfb28b 100644 --- a/examples/angular/pagination/package.json +++ b/examples/angular/pagination/package.json @@ -9,19 +9,20 @@ "watch": "ng build --watch --configuration development" }, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "5.8.3" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/examples/angular/pagination/src/app/app.config.ts b/examples/angular/pagination/src/app/app.config.ts index dc3189ba84b..b36a88a566c 100644 --- a/examples/angular/pagination/src/app/app.config.ts +++ b/examples/angular/pagination/src/app/app.config.ts @@ -3,17 +3,14 @@ import { withFetch, withInterceptors, } from '@angular/common/http' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' import { projectsMockInterceptor } from './api/projects-mock.interceptor' import type { ApplicationConfig } from '@angular/core' export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withInterceptors([projectsMockInterceptor]), withFetch()), - provideTanStackQuery(new QueryClient(), withDevtools()), + provideTanStackQuery(() => new QueryClient(), withDevtools()), ], } diff --git a/examples/angular/pagination/src/app/components/example.component.ts b/examples/angular/pagination/src/app/components/example.component.ts index 217d7d4e40b..a1b02eec349 100644 --- a/examples/angular/pagination/src/app/components/example.component.ts +++ b/examples/angular/pagination/src/app/components/example.component.ts @@ -10,8 +10,7 @@ import { QueryClient, injectQuery, keepPreviousData, - noop, -} from '@tanstack/angular-query-experimental' +} from '@tanstack/angular-query' import { lastValueFrom } from 'rxjs' import { ProjectsService } from '../services/projects.service' diff --git a/examples/angular/query-options-from-a-service/angular.json b/examples/angular/query-options-from-a-service/angular.json index 3815edc28d3..8c72de140c0 100644 --- a/examples/angular/query-options-from-a-service/angular.json +++ b/examples/angular/query-options-from-a-service/angular.json @@ -82,6 +82,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, "configurations": { "production": { "buildTarget": "query-options-from-a-service:build:production" diff --git a/examples/angular/query-options-from-a-service/package.json b/examples/angular/query-options-from-a-service/package.json index 12a0ba48c17..93ba8214cca 100644 --- a/examples/angular/query-options-from-a-service/package.json +++ b/examples/angular/query-options-from-a-service/package.json @@ -9,20 +9,21 @@ }, "private": true, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@angular/router": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@angular/router": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "5.8.3" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/examples/angular/query-options-from-a-service/src/app/app.config.ts b/examples/angular/query-options-from-a-service/src/app/app.config.ts index dd6675f997b..06f5240bdfe 100644 --- a/examples/angular/query-options-from-a-service/src/app/app.config.ts +++ b/examples/angular/query-options-from-a-service/src/app/app.config.ts @@ -1,11 +1,8 @@ import { provideHttpClient, withFetch } from '@angular/common/http' import { provideRouter, withComponentInputBinding } from '@angular/router' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { withDevtools } from '@tanstack/angular-query-devtools' import { routes } from './app.routes' import type { ApplicationConfig } from '@angular/core' @@ -13,6 +10,6 @@ export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withFetch()), provideRouter(routes, withComponentInputBinding()), - provideTanStackQuery(new QueryClient(), withDevtools()), + provideTanStackQuery(() => new QueryClient(), withDevtools()), ], } diff --git a/examples/angular/query-options-from-a-service/src/app/components/post.component.ts b/examples/angular/query-options-from-a-service/src/app/components/post.component.ts index 87bebeb44d0..68cc4bf1972 100644 --- a/examples/angular/query-options-from-a-service/src/app/components/post.component.ts +++ b/examples/angular/query-options-from-a-service/src/app/components/post.component.ts @@ -6,7 +6,7 @@ import { numberAttribute, } from '@angular/core' import { RouterLink } from '@angular/router' -import { injectQuery } from '@tanstack/angular-query-experimental' +import { injectQuery } from '@tanstack/angular-query' import { QueriesService } from '../services/queries-service' @Component({ diff --git a/examples/angular/query-options-from-a-service/src/app/components/posts.component.ts b/examples/angular/query-options-from-a-service/src/app/components/posts.component.ts index ed26b0aed7f..4d526c2fe61 100644 --- a/examples/angular/query-options-from-a-service/src/app/components/posts.component.ts +++ b/examples/angular/query-options-from-a-service/src/app/components/posts.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core' import { RouterLink } from '@angular/router' -import { QueryClient, injectQuery } from '@tanstack/angular-query-experimental' +import { QueryClient, injectQuery } from '@tanstack/angular-query' import { QueriesService } from '../services/queries-service' @Component({ diff --git a/examples/angular/query-options-from-a-service/src/app/services/queries-service.ts b/examples/angular/query-options-from-a-service/src/app/services/queries-service.ts index 70ad35c5d79..c1f01e62b6a 100644 --- a/examples/angular/query-options-from-a-service/src/app/services/queries-service.ts +++ b/examples/angular/query-options-from-a-service/src/app/services/queries-service.ts @@ -1,6 +1,6 @@ import { Injectable, inject } from '@angular/core' import { lastValueFrom } from 'rxjs' -import { queryOptions } from '@tanstack/angular-query-experimental' +import { queryOptions } from '@tanstack/angular-query' import { HttpClient } from '@angular/common/http' export interface Post { diff --git a/examples/angular/router/angular.json b/examples/angular/router/angular.json index b52ac654f31..3bcecbc602f 100644 --- a/examples/angular/router/angular.json +++ b/examples/angular/router/angular.json @@ -82,6 +82,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, "configurations": { "production": { "buildTarget": "router:build:production" diff --git a/examples/angular/router/package.json b/examples/angular/router/package.json index 0f459983f3b..3cdb8945092 100644 --- a/examples/angular/router/package.json +++ b/examples/angular/router/package.json @@ -9,20 +9,21 @@ }, "private": true, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@angular/router": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@angular/router": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "5.8.3" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/examples/angular/router/src/app/app.config.ts b/examples/angular/router/src/app/app.config.ts index 3fbec800b1f..b5a2a890f7f 100644 --- a/examples/angular/router/src/app/app.config.ts +++ b/examples/angular/router/src/app/app.config.ts @@ -1,18 +1,15 @@ import { provideHttpClient, withFetch } from '@angular/common/http' import { provideRouter, withComponentInputBinding } from '@angular/router' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { withDevtools } from '@tanstack/angular-query-devtools' import { routes } from './app.routes' import type { ApplicationConfig } from '@angular/core' export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withFetch()), - provideTanStackQuery(new QueryClient(), withDevtools()), + provideTanStackQuery(() => new QueryClient(), withDevtools()), provideRouter(routes, withComponentInputBinding()), ], } diff --git a/examples/angular/router/src/app/components/post.component.ts b/examples/angular/router/src/app/components/post.component.ts index 118adc42ba9..56191ea1bdd 100644 --- a/examples/angular/router/src/app/components/post.component.ts +++ b/examples/angular/router/src/app/components/post.component.ts @@ -6,7 +6,7 @@ import { numberAttribute, } from '@angular/core' import { RouterLink } from '@angular/router' -import { injectQuery } from '@tanstack/angular-query-experimental' +import { injectQuery } from '@tanstack/angular-query' import { lastValueFrom } from 'rxjs' import { PostsService } from '../services/posts-service' diff --git a/examples/angular/router/src/app/components/posts.component.ts b/examples/angular/router/src/app/components/posts.component.ts index 5284a749085..7d65b5b922c 100644 --- a/examples/angular/router/src/app/components/posts.component.ts +++ b/examples/angular/router/src/app/components/posts.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core' import { RouterLink } from '@angular/router' -import { QueryClient, injectQuery } from '@tanstack/angular-query-experimental' +import { QueryClient, injectQuery } from '@tanstack/angular-query' import { lastValueFrom } from 'rxjs' import { PostsService } from '../services/posts-service' diff --git a/examples/angular/rxjs/angular.json b/examples/angular/rxjs/angular.json index 9a79ecf1a36..d1b2d572342 100644 --- a/examples/angular/rxjs/angular.json +++ b/examples/angular/rxjs/angular.json @@ -82,6 +82,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, "configurations": { "production": { "buildTarget": "rxjs:build:production" diff --git a/examples/angular/rxjs/package.json b/examples/angular/rxjs/package.json index 187828ba62c..d169032dbf2 100644 --- a/examples/angular/rxjs/package.json +++ b/examples/angular/rxjs/package.json @@ -9,20 +9,21 @@ "watch": "ng build --watch --configuration development" }, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/forms": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/forms": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "5.8.3" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/examples/angular/rxjs/src/app/app.config.ts b/examples/angular/rxjs/src/app/app.config.ts index 27eb15a53b1..8a2ebb37baf 100644 --- a/examples/angular/rxjs/src/app/app.config.ts +++ b/examples/angular/rxjs/src/app/app.config.ts @@ -3,11 +3,8 @@ import { withFetch, withInterceptors, } from '@angular/common/http' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' import { autocompleteMockInterceptor } from './api/autocomplete-mock.interceptor' import type { ApplicationConfig } from '@angular/core' @@ -18,13 +15,14 @@ export const appConfig: ApplicationConfig = { withInterceptors([autocompleteMockInterceptor]), ), provideTanStackQuery( - new QueryClient({ - defaultOptions: { - queries: { - gcTime: 1000 * 60 * 60 * 24, // 24 hours + () => + new QueryClient({ + defaultOptions: { + queries: { + gcTime: 1000 * 60 * 60 * 24, // 24 hours + }, }, - }, - }), + }), withDevtools(), ), ], diff --git a/examples/angular/rxjs/src/app/components/example.component.ts b/examples/angular/rxjs/src/app/components/example.component.ts index 16e93735a98..e7aa3216215 100644 --- a/examples/angular/rxjs/src/app/components/example.component.ts +++ b/examples/angular/rxjs/src/app/components/example.component.ts @@ -4,7 +4,7 @@ import { NonNullableFormBuilder, ReactiveFormsModule } from '@angular/forms' import { injectQuery, keepPreviousData, -} from '@tanstack/angular-query-experimental' +} from '@tanstack/angular-query' import { debounceTime, distinctUntilChanged, lastValueFrom } from 'rxjs' import { AutocompleteService } from '../services/autocomplete-service' diff --git a/examples/angular/simple/angular.json b/examples/angular/simple/angular.json index 0075533a99a..7da2f4f0798 100644 --- a/examples/angular/simple/angular.json +++ b/examples/angular/simple/angular.json @@ -82,6 +82,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, "configurations": { "production": { "buildTarget": "simple:build:production" diff --git a/examples/angular/simple/package.json b/examples/angular/simple/package.json index 08ada90a1fe..c945af1643d 100644 --- a/examples/angular/simple/package.json +++ b/examples/angular/simple/package.json @@ -9,19 +9,20 @@ }, "private": true, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "5.8.3" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/examples/angular/simple/src/app/app.config.ts b/examples/angular/simple/src/app/app.config.ts index 9c7eda25974..6d8eec79b17 100644 --- a/examples/angular/simple/src/app/app.config.ts +++ b/examples/angular/simple/src/app/app.config.ts @@ -1,14 +1,11 @@ import { provideHttpClient, withFetch } from '@angular/common/http' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' -import { withDevtools } from '@tanstack/angular-query-experimental/devtools' +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' import type { ApplicationConfig } from '@angular/core' export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withFetch()), - provideTanStackQuery(new QueryClient(), withDevtools()), + provideTanStackQuery(() => new QueryClient(), withDevtools()), ], } diff --git a/examples/angular/simple/src/app/components/simple-example.component.ts b/examples/angular/simple/src/app/components/simple-example.component.ts index fe43999eb00..461cfc65878 100644 --- a/examples/angular/simple/src/app/components/simple-example.component.ts +++ b/examples/angular/simple/src/app/components/simple-example.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core' -import { injectQuery } from '@tanstack/angular-query-experimental' +import { injectQuery } from '@tanstack/angular-query' import { HttpClient } from '@angular/common/http' import { lastValueFrom } from 'rxjs' diff --git a/examples/angular/ssr-persist/.devcontainer/devcontainer.json b/examples/angular/ssr-persist/.devcontainer/devcontainer.json new file mode 100644 index 00000000000..365adf8f4c3 --- /dev/null +++ b/examples/angular/ssr-persist/.devcontainer/devcontainer.json @@ -0,0 +1,4 @@ +{ + "name": "Node.js", + "image": "mcr.microsoft.com/devcontainers/javascript-node:22" +} diff --git a/examples/angular/ssr-persist/.eslintrc.cjs b/examples/angular/ssr-persist/.eslintrc.cjs new file mode 100644 index 00000000000..cca134ce166 --- /dev/null +++ b/examples/angular/ssr-persist/.eslintrc.cjs @@ -0,0 +1,6 @@ +// @ts-check + +/** @type {import('eslint').Linter.Config} */ +const config = {} + +module.exports = config diff --git a/examples/angular/ssr-persist/README.md b/examples/angular/ssr-persist/README.md new file mode 100644 index 00000000000..e981642c723 --- /dev/null +++ b/examples/angular/ssr-persist/README.md @@ -0,0 +1,14 @@ +# TanStack Query Angular SSR + persistence example + +Combines [SSR/hydration](https://tanstack.com/query/latest/docs/framework/angular/guides/ssr), a `localStorage` persister, and a **client-only island**: `ClientPersistDemoComponent` is mounted with `afterNextRender`, so its `injectQuery` `queryFn` does not run during SSR (unlike `@defer` main content, which is still rendered on the server for incremental hydration). + +- **Server:** same bootstrap config shape as the base SSR example; `withPersistQueryClient` uses a factory and skips work when not in the browser. +- **Client:** `showClientDemo` is set to `true` in `afterNextRender`, then `` is created — optional `dehydrateOptions.shouldDehydrateQuery` can scope persistence to `client-persist` query keys only. + +To run: + +- From the repo root: `pnpm install` then + `pnpm --filter @tanstack/query-example-angular-ssr-persist start` +- Production SSR server after build: + `pnpm --filter @tanstack/query-example-angular-ssr-persist run build` + then `pnpm --filter @tanstack/query-example-angular-ssr-persist run serve:ssr` diff --git a/examples/angular/ssr-persist/angular.json b/examples/angular/ssr-persist/angular.json new file mode 100644 index 00000000000..b4bdec992b9 --- /dev/null +++ b/examples/angular/ssr-persist/angular.json @@ -0,0 +1,140 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "cli": { + "packageManager": "pnpm", + "analytics": false, + "cache": { + "enabled": false + } + }, + "newProjectRoot": "projects", + "projects": { + "ssr-persist": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "inlineTemplate": true, + "inlineStyle": true, + "skipTests": true + }, + "@schematics/angular:class": { + "skipTests": true + }, + "@schematics/angular:directive": { + "skipTests": true + }, + "@schematics/angular:guard": { + "skipTests": true + }, + "@schematics/angular:interceptor": { + "skipTests": true + }, + "@schematics/angular:pipe": { + "skipTests": true + }, + "@schematics/angular:resolver": { + "skipTests": true + }, + "@schematics/angular:service": { + "skipTests": true + } + }, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular/build:application", + "options": { + "outputPath": "dist/ssr-persist", + "index": "src/index.html", + "browser": "src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "tsconfig.app.json", + "styles": ["src/styles.css"], + "scripts": [], + "server": "src/main.server.ts", + "outputMode": "server", + "security": { + "allowedHosts": ["localhost", "127.0.0.1"] + }, + "ssr": { + "entry": "src/server.ts" + } + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, + "configurations": { + "production": { + "buildTarget": "ssr-persist:build:production" + }, + "development": { + "buildTarget": "ssr-persist:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular/build:extract-i18n", + "options": { + "buildTarget": "ssr-persist:build" + } + } + } + } + }, + "schematics": { + "@schematics/angular:component": { + "type": "component" + }, + "@schematics/angular:directive": { + "type": "directive" + }, + "@schematics/angular:service": { + "type": "service" + }, + "@schematics/angular:guard": { + "typeSeparator": "." + }, + "@schematics/angular:interceptor": { + "typeSeparator": "." + }, + "@schematics/angular:module": { + "typeSeparator": "." + }, + "@schematics/angular:pipe": { + "typeSeparator": "." + }, + "@schematics/angular:resolver": { + "typeSeparator": "." + } + } +} diff --git a/examples/angular/ssr-persist/package.json b/examples/angular/ssr-persist/package.json new file mode 100644 index 00000000000..547277b5e6f --- /dev/null +++ b/examples/angular/ssr-persist/package.json @@ -0,0 +1,35 @@ +{ + "name": "@tanstack/query-example-angular-ssr-persist", + "type": "module", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "serve:ssr": "node dist/ssr-persist/server/server.mjs" + }, + "private": true, + "dependencies": { + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@angular/platform-server": "^22.0.0", + "@angular/ssr": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", + "@tanstack/angular-query-persist-client": "workspace:*", + "@tanstack/query-async-storage-persister": "workspace:*", + "express": "^5.1.0", + "rxjs": "^7.8.2", + "tslib": "^2.8.1", + "zone.js": "0.16.1" + }, + "devDependencies": { + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "@types/express": "^5.0.1", + "typescript": "6.0.3" + } +} diff --git a/examples/angular/ssr-persist/src/app/app.component.ts b/examples/angular/ssr-persist/src/app/app.component.ts new file mode 100644 index 00000000000..ffdde21e388 --- /dev/null +++ b/examples/angular/ssr-persist/src/app/app.component.ts @@ -0,0 +1,127 @@ +import { + ChangeDetectionStrategy, + Component, + afterNextRender, + signal, +} from '@angular/core' +import { ClientPersistDemoComponent } from './components/client-persist-demo.component' +import { PostsComponent } from './components/posts.component' + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'ssr-persist-example', + imports: [ClientPersistDemoComponent, PostsComponent], + template: ` +
+
+

Angular SSR + client-only island + persistence

+

SSR queries vs client-only persisted queries

+

+ Posts use queryKey: ['posts'] and run on the server. + Configure the persister with + dehydrateOptions.shouldDehydrateQuery if you want only + client-persist keys in localStorage. +

+

+ The panel below is mounted only in the browser via + afterNextRender, so its query never runs during SSR. + After the first visit, hard-reload: the timestamp can be restored from + persistence while posts render from SSR again. +

+
+ +
+

Server data

+ +
+ +
+

Client-only (afterNextRender)

+ @if (showClientDemo()) { + + } @else { +

+ Server render: this placeholder has no + client-persist-demo component yet — it is created after + the first browser frame via afterNextRender. +

+ } +
+
+ `, + styles: ` + .page { + max-width: 960px; + margin: 0 auto; + padding: 48px 20px 72px; + } + + .hero { + margin-bottom: 32px; + } + + .eyebrow { + margin: 0 0 8px; + font-size: 12px; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: #9b5c00; + } + + h1 { + margin: 0 0 12px; + font-size: clamp(2.2rem, 5vw, 4rem); + line-height: 1; + } + + .lede { + max-width: 640px; + margin: 0 0 12px; + font-size: 1rem; + line-height: 1.6; + color: #4b5563; + } + + .hint { + font-size: 0.95rem; + color: #6b7280; + } + + code { + font-size: 0.88em; + padding: 0.1em 0.35em; + border-radius: 4px; + background: #f3f4f6; + } + + .region { + margin-bottom: 40px; + } + + .region-title { + margin: 0 0 16px; + font-size: 1.25rem; + color: #1f2937; + } + + .placeholder { + margin: 0; + padding: 16px; + border-radius: 12px; + background: #f9fafb; + color: #6b7280; + line-height: 1.5; + } + `, +}) +export class SsrPersistExampleComponent { + /** When `true`, `ClientPersistDemoComponent` exists only in the browser (not during SSR). */ + readonly showClientDemo = signal(false) + + constructor() { + afterNextRender(() => { + this.showClientDemo.set(true) + }) + } +} diff --git a/examples/angular/ssr-persist/src/app/app.config.server.ts b/examples/angular/ssr-persist/src/app/app.config.server.ts new file mode 100644 index 00000000000..a1a957f51c4 --- /dev/null +++ b/examples/angular/ssr-persist/src/app/app.config.server.ts @@ -0,0 +1,8 @@ +import { mergeApplicationConfig } from '@angular/core' +import { provideServerRendering, withRoutes } from '@angular/ssr' +import { appConfig } from './app.config' +import { serverRoutes } from './app.routes.server' + +export const serverConfig = mergeApplicationConfig(appConfig, { + providers: [provideServerRendering(withRoutes(serverRoutes))], +}) diff --git a/examples/angular/ssr-persist/src/app/app.config.ts b/examples/angular/ssr-persist/src/app/app.config.ts new file mode 100644 index 00000000000..d8bb855fe3a --- /dev/null +++ b/examples/angular/ssr-persist/src/app/app.config.ts @@ -0,0 +1,31 @@ +import { provideHttpClient, withFetch } from '@angular/common/http' +import type { ApplicationConfig } from '@angular/core' +import { + provideClientHydration, + withEventReplay, +} from '@angular/platform-browser' +import { provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' +import { withPersistQueryClient } from '@tanstack/angular-query-persist-client' +import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister' +import { PERSIST_STORAGE_KEY, createQueryClient } from './query-client' + +export const appConfig: ApplicationConfig = { + providers: [ + provideHttpClient(withFetch()), + provideClientHydration(withEventReplay()), + provideTanStackQuery( + createQueryClient, + withDevtools(), + withPersistQueryClient(() => ({ + persistOptions: { + persister: createAsyncStoragePersister({ + storage: localStorage, + key: PERSIST_STORAGE_KEY, + throttleTime: 1000, + }), + }, + })), + ), + ], +} diff --git a/examples/angular/ssr-persist/src/app/app.routes.server.ts b/examples/angular/ssr-persist/src/app/app.routes.server.ts new file mode 100644 index 00000000000..09fcfa3cc95 --- /dev/null +++ b/examples/angular/ssr-persist/src/app/app.routes.server.ts @@ -0,0 +1,9 @@ +import { RenderMode } from '@angular/ssr' +import type { ServerRoute } from '@angular/ssr' + +export const serverRoutes: Array = [ + { + path: '**', + renderMode: RenderMode.Server, + }, +] diff --git a/examples/angular/ssr-persist/src/app/components/client-persist-demo.component.ts b/examples/angular/ssr-persist/src/app/components/client-persist-demo.component.ts new file mode 100644 index 00000000000..41ba96cda48 --- /dev/null +++ b/examples/angular/ssr-persist/src/app/components/client-persist-demo.component.ts @@ -0,0 +1,84 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core' +import { injectQuery } from '@tanstack/angular-query' +import { CLIENT_PERSIST_QUERY_ROOT } from '../query-persist-scope' + +/** + * Mounted only in the browser (parent uses `afterNextRender`), so `queryFn` is not run during SSR. + * Pair with `dehydrateOptions.shouldDehydrateQuery` if you want only `client-persist` keys in storage. + */ +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'client-persist-demo', + template: ` +
+

Client-only island

+

Client-only persisted query

+ @if (demo.isPending()) { +

Loading client-only data…

+ } @else if (demo.isError()) { +

Failed to load.

+ } @else if (demo.data(); as data) { +

{{ data.createdAt }}

+

+ This value is stored under the client-persist query key. + Hard-reload the page: it should reappear from persistence while the + posts list above is rendered from SSR again. +

+ } +
+ `, + styles: ` + .panel { + margin-top: 8px; + padding: 20px; + border-radius: 18px; + border: 1px dashed #c4b5a0; + background: #fffefb; + } + + .badge { + margin: 0 0 8px; + font-size: 11px; + font-weight: 700; + letter-spacing: 0.1em; + text-transform: uppercase; + color: #7c5a10; + } + + h3 { + margin: 0 0 12px; + font-size: 1.1rem; + } + + .mono { + margin: 0 0 12px; + font-family: ui-monospace, monospace; + font-size: 0.85rem; + word-break: break-all; + } + + .note { + margin: 0; + font-size: 0.9rem; + line-height: 1.5; + color: #4b5563; + } + + code { + font-size: 0.88em; + padding: 0.1em 0.35em; + border-radius: 4px; + background: #f3f4f6; + } + `, +}) +export class ClientPersistDemoComponent { + readonly demo = injectQuery(() => ({ + queryKey: [CLIENT_PERSIST_QUERY_ROOT, 'timestamp-demo'], + queryFn: async () => { + await new Promise((r) => setTimeout(r, 100)) + return { createdAt: new Date().toISOString() } + }, + staleTime: Infinity, + })) +} diff --git a/examples/angular/ssr-persist/src/app/components/posts.component.ts b/examples/angular/ssr-persist/src/app/components/posts.component.ts new file mode 100644 index 00000000000..e9b13754d57 --- /dev/null +++ b/examples/angular/ssr-persist/src/app/components/posts.component.ts @@ -0,0 +1,70 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core' +import { injectQuery } from '@tanstack/angular-query' +import { lastValueFrom } from 'rxjs' +import { PostsService } from '../services/posts.service' + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'posts', + template: ` + @if (postsQuery.isPending()) { +

Loading posts...

+ } @else if (postsQuery.isError()) { +

Failed to load posts.

+ } @else { +
+ @for (post of postsQuery.data(); track post.id) { +
+

Post #{{ post.id }}

+

{{ post.title }}

+

{{ post.body }}

+
+ } +
+ } + `, + styles: ` + .grid { + display: grid; + gap: 16px; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + } + + .card { + padding: 20px; + border: 1px solid #eadfcb; + border-radius: 18px; + background: #fffdf8; + box-shadow: 0 12px 30px rgba(123, 88, 31, 0.08); + } + + .meta { + margin: 0 0 10px; + font-size: 12px; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + color: #8b5e34; + } + + h2 { + margin: 0 0 10px; + font-size: 1.1rem; + line-height: 1.3; + } + + p { + margin: 0; + line-height: 1.5; + color: #374151; + } + `, +}) +export class PostsComponent { + readonly #postsService = inject(PostsService) + + readonly postsQuery = injectQuery(() => ({ + queryKey: ['posts'], + queryFn: () => lastValueFrom(this.#postsService.allPosts$()), + })) +} diff --git a/examples/angular/ssr-persist/src/app/query-client.ts b/examples/angular/ssr-persist/src/app/query-client.ts new file mode 100644 index 00000000000..de7b2e1930b --- /dev/null +++ b/examples/angular/ssr-persist/src/app/query-client.ts @@ -0,0 +1,21 @@ +import { isPlatformServer } from '@angular/common' +import { PLATFORM_ID, inject } from '@angular/core' +import { QueryClient } from '@tanstack/angular-query' + +export const PERSIST_STORAGE_KEY = 'tanstack-query-angular-ssr-persist-example' + +export const SHARED_QUERY_DEFAULTS = { + staleTime: 1000 * 30, + gcTime: 1000 * 60 * 60 * 24, +} as const + +export function createQueryClient() { + return new QueryClient({ + defaultOptions: { + queries: { + ...SHARED_QUERY_DEFAULTS, + ...(isPlatformServer(inject(PLATFORM_ID)) ? { retry: false } : {}), + }, + }, + }) +} diff --git a/examples/angular/ssr-persist/src/app/query-persist-scope.ts b/examples/angular/ssr-persist/src/app/query-persist-scope.ts new file mode 100644 index 00000000000..08a420f7932 --- /dev/null +++ b/examples/angular/ssr-persist/src/app/query-persist-scope.ts @@ -0,0 +1,5 @@ +/** + * Query key prefix for data that should be written to `localStorage` by the global persister. + * SSR queries (e.g. `['posts']`) use different keys and are excluded in `dehydrateOptions`. + */ +export const CLIENT_PERSIST_QUERY_ROOT = 'client-persist' as const diff --git a/examples/angular/ssr-persist/src/app/services/posts.service.ts b/examples/angular/ssr-persist/src/app/services/posts.service.ts new file mode 100644 index 00000000000..edb8e084f0e --- /dev/null +++ b/examples/angular/ssr-persist/src/app/services/posts.service.ts @@ -0,0 +1,63 @@ +import { Injectable } from '@angular/core' +import { of, tap } from 'rxjs' +import { delay } from 'rxjs/operators' + +@Injectable({ + providedIn: 'root', +}) +export class PostsService { + allPosts$ = () => + of(posts).pipe( + tap(() => console.log('fetching posts')), + delay(50), + ) +} + +export interface Post { + id: number + title: string + body: string +} + +const posts: Array = [ + { + id: 1, + title: 'Render on the server', + body: 'The initial HTML is produced by Angular SSR before the browser bootstraps the app.', + }, + { + id: 2, + title: 'Hydrate on the client', + body: 'Angular reuses the rendered DOM and turns it into a live client application.', + }, + { + id: 3, + title: 'Query on both sides', + body: 'TanStack Query runs during SSR, hydrates on the client, and the persisted cache can speed up the next full load.', + }, + { + id: 3.5, + title: 'Persist after hydration', + body: 'withPersistQueryClient uses a factory so localStorage is only touched in the browser, not during server render.', + }, + { + id: 4, + title: 'No API needed', + body: 'This example uses a deterministic in-memory data source so the SSR example works without external network access.', + }, + { + id: 5, + title: 'Keep the setup small', + body: 'Only the Angular CLI SSR pieces remain: main.server.ts, server.ts and the server application config.', + }, + { + id: 6, + title: 'Match the other examples', + body: 'The rest of the app keeps the same lightweight structure as the existing Angular examples in this repo.', + }, + { + id: 7, + title: 'Persist after hydration', + body: 'withPersistQueryClient uses a factory so localStorage is only touched in the browser, not during server render.', + }, +] diff --git a/examples/angular/ssr-persist/src/index.html b/examples/angular/ssr-persist/src/index.html new file mode 100644 index 00000000000..c00f1bf3ca5 --- /dev/null +++ b/examples/angular/ssr-persist/src/index.html @@ -0,0 +1,12 @@ + + + + + TanStack Query Angular SSR + persist example + + + + + + + diff --git a/examples/angular/ssr-persist/src/main.server.ts b/examples/angular/ssr-persist/src/main.server.ts new file mode 100644 index 00000000000..1bdb237f23f --- /dev/null +++ b/examples/angular/ssr-persist/src/main.server.ts @@ -0,0 +1,11 @@ +import { + bootstrapApplication, + type BootstrapContext, +} from '@angular/platform-browser' +import { serverConfig } from './app/app.config.server' +import { SsrPersistExampleComponent } from './app/app.component' + +const bootstrap = (context: BootstrapContext) => + bootstrapApplication(SsrPersistExampleComponent, serverConfig, context) + +export default bootstrap diff --git a/examples/angular/ssr-persist/src/main.ts b/examples/angular/ssr-persist/src/main.ts new file mode 100644 index 00000000000..9c2c5ea1079 --- /dev/null +++ b/examples/angular/ssr-persist/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser' +import { appConfig } from './app/app.config' +import { SsrPersistExampleComponent } from './app/app.component' + +bootstrapApplication(SsrPersistExampleComponent, appConfig).catch((err) => + console.error(err), +) diff --git a/examples/angular/ssr-persist/src/server.ts b/examples/angular/ssr-persist/src/server.ts new file mode 100644 index 00000000000..db670c6eb0d --- /dev/null +++ b/examples/angular/ssr-persist/src/server.ts @@ -0,0 +1,43 @@ +import { + AngularNodeAppEngine, + createNodeRequestHandler, + isMainModule, + writeResponseToNodeResponse, +} from '@angular/ssr/node' +import express from 'express' +import { join } from 'node:path' + +const browserDistFolder = join(import.meta.dirname, '../browser') + +const app = express() +const angularApp = new AngularNodeAppEngine() + +app.use( + express.static(browserDistFolder, { + maxAge: '1y', + index: false, + redirect: false, + }), +) + +app.use((req, res, next) => { + angularApp + .handle(req) + .then((response) => + response ? writeResponseToNodeResponse(response, res) : next(), + ) + .catch(next) +}) + +if (isMainModule(import.meta.url)) { + const port = process.env['PORT'] || 4000 + app.listen(port, (error) => { + if (error) { + throw error + } + + console.log(`Node Express server listening on http://localhost:${port}`) + }) +} + +export const reqHandler = createNodeRequestHandler(app) diff --git a/examples/angular/ssr-persist/src/styles.css b/examples/angular/ssr-persist/src/styles.css new file mode 100644 index 00000000000..6718c269c49 --- /dev/null +++ b/examples/angular/ssr-persist/src/styles.css @@ -0,0 +1,16 @@ +body { + margin: 0; + font-family: + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + sans-serif; + background: #faf8f2; + color: #1b1f23; +} + +button { + font: inherit; +} diff --git a/examples/angular/ssr-persist/tsconfig.app.json b/examples/angular/ssr-persist/tsconfig.app.json new file mode 100644 index 00000000000..00e9b764198 --- /dev/null +++ b/examples/angular/ssr-persist/tsconfig.app.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": ["node"] + }, + "include": ["src/**/*.ts"] +} diff --git a/examples/angular/ssr-persist/tsconfig.json b/examples/angular/ssr-persist/tsconfig.json new file mode 100644 index 00000000000..5aa05d2d231 --- /dev/null +++ b/examples/angular/ssr-persist/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "isolatedModules": true, + "experimentalDecorators": true, + "importHelpers": true, + "target": "ES2022", + "module": "preserve" + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "typeCheckHostBindings": true, + "strictTemplates": true + }, + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/examples/angular/ssr/.devcontainer/devcontainer.json b/examples/angular/ssr/.devcontainer/devcontainer.json new file mode 100644 index 00000000000..365adf8f4c3 --- /dev/null +++ b/examples/angular/ssr/.devcontainer/devcontainer.json @@ -0,0 +1,4 @@ +{ + "name": "Node.js", + "image": "mcr.microsoft.com/devcontainers/javascript-node:22" +} diff --git a/examples/angular/ssr/.eslintrc.cjs b/examples/angular/ssr/.eslintrc.cjs new file mode 100644 index 00000000000..cca134ce166 --- /dev/null +++ b/examples/angular/ssr/.eslintrc.cjs @@ -0,0 +1,6 @@ +// @ts-check + +/** @type {import('eslint').Linter.Config} */ +const config = {} + +module.exports = config diff --git a/examples/angular/ssr/README.md b/examples/angular/ssr/README.md new file mode 100644 index 00000000000..b15e6f599d1 --- /dev/null +++ b/examples/angular/ssr/README.md @@ -0,0 +1,6 @@ +# TanStack Query Angular SSR example + +To run this example: + +- `npm install` or `yarn` or `pnpm i` or `bun i` +- `npm run start` or `yarn start` or `pnpm start` or `bun start` diff --git a/examples/angular/ssr/angular.json b/examples/angular/ssr/angular.json new file mode 100644 index 00000000000..1e393174cf2 --- /dev/null +++ b/examples/angular/ssr/angular.json @@ -0,0 +1,140 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "cli": { + "packageManager": "pnpm", + "analytics": false, + "cache": { + "enabled": false + } + }, + "newProjectRoot": "projects", + "projects": { + "ssr": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "inlineTemplate": true, + "inlineStyle": true, + "skipTests": true + }, + "@schematics/angular:class": { + "skipTests": true + }, + "@schematics/angular:directive": { + "skipTests": true + }, + "@schematics/angular:guard": { + "skipTests": true + }, + "@schematics/angular:interceptor": { + "skipTests": true + }, + "@schematics/angular:pipe": { + "skipTests": true + }, + "@schematics/angular:resolver": { + "skipTests": true + }, + "@schematics/angular:service": { + "skipTests": true + } + }, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular/build:application", + "options": { + "outputPath": "dist/ssr", + "index": "src/index.html", + "browser": "src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "tsconfig.app.json", + "styles": ["src/styles.css"], + "scripts": [], + "server": "src/main.server.ts", + "outputMode": "server", + "security": { + "allowedHosts": ["localhost", "127.0.0.1"] + }, + "ssr": { + "entry": "src/server.ts" + } + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular/build:dev-server", + "options": { + "prebundle": { "exclude": ["@angular"] } + }, + "configurations": { + "production": { + "buildTarget": "ssr:build:production" + }, + "development": { + "buildTarget": "ssr:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular/build:extract-i18n", + "options": { + "buildTarget": "ssr:build" + } + } + } + } + }, + "schematics": { + "@schematics/angular:component": { + "type": "component" + }, + "@schematics/angular:directive": { + "type": "directive" + }, + "@schematics/angular:service": { + "type": "service" + }, + "@schematics/angular:guard": { + "typeSeparator": "." + }, + "@schematics/angular:interceptor": { + "typeSeparator": "." + }, + "@schematics/angular:module": { + "typeSeparator": "." + }, + "@schematics/angular:pipe": { + "typeSeparator": "." + }, + "@schematics/angular:resolver": { + "typeSeparator": "." + } + } +} diff --git a/examples/angular/ssr/package.json b/examples/angular/ssr/package.json new file mode 100644 index 00000000000..167ba73635b --- /dev/null +++ b/examples/angular/ssr/package.json @@ -0,0 +1,33 @@ +{ + "name": "@tanstack/query-example-angular-ssr", + "type": "module", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "serve:ssr": "node dist/ssr/server/server.mjs" + }, + "private": true, + "dependencies": { + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@angular/platform-server": "^22.0.0", + "@angular/ssr": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", + "express": "^5.1.0", + "rxjs": "^7.8.2", + "tslib": "^2.8.1", + "zone.js": "0.16.1" + }, + "devDependencies": { + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "@types/express": "^5.0.1", + "typescript": "6.0.3" + } +} diff --git a/examples/angular/ssr/src/app/app.component.ts b/examples/angular/ssr/src/app/app.component.ts new file mode 100644 index 00000000000..1f17c32569c --- /dev/null +++ b/examples/angular/ssr/src/app/app.component.ts @@ -0,0 +1,57 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core' +import { PostsComponent } from './components/posts.component' + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'ssr-example', + imports: [PostsComponent], + template: ` +
+
+

Angular SSR

+

Server-rendered posts with TanStack Query

+

+ The first render comes from the server. Angular then hydrates the app + on the client and TanStack Query continues from a fresh client cache. +

+
+ + +
+ `, + styles: ` + .page { + max-width: 960px; + margin: 0 auto; + padding: 48px 20px 72px; + } + + .hero { + margin-bottom: 32px; + } + + .eyebrow { + margin: 0 0 8px; + font-size: 12px; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: #9b5c00; + } + + h1 { + margin: 0 0 12px; + font-size: clamp(2.2rem, 5vw, 4rem); + line-height: 1; + } + + .lede { + max-width: 640px; + margin: 0; + font-size: 1rem; + line-height: 1.6; + color: #4b5563; + } + `, +}) +export class SsrExampleComponent {} diff --git a/examples/angular/ssr/src/app/app.config.server.ts b/examples/angular/ssr/src/app/app.config.server.ts new file mode 100644 index 00000000000..a1a957f51c4 --- /dev/null +++ b/examples/angular/ssr/src/app/app.config.server.ts @@ -0,0 +1,8 @@ +import { mergeApplicationConfig } from '@angular/core' +import { provideServerRendering, withRoutes } from '@angular/ssr' +import { appConfig } from './app.config' +import { serverRoutes } from './app.routes.server' + +export const serverConfig = mergeApplicationConfig(appConfig, { + providers: [provideServerRendering(withRoutes(serverRoutes))], +}) diff --git a/examples/angular/ssr/src/app/app.config.ts b/examples/angular/ssr/src/app/app.config.ts new file mode 100644 index 00000000000..05322a559a5 --- /dev/null +++ b/examples/angular/ssr/src/app/app.config.ts @@ -0,0 +1,17 @@ +import { provideHttpClient, withFetch } from '@angular/common/http' +import type { ApplicationConfig } from '@angular/core' +import { + provideClientHydration, + withEventReplay, +} from '@angular/platform-browser' +import { provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' +import { createQueryClient } from './query-client' + +export const appConfig: ApplicationConfig = { + providers: [ + provideHttpClient(withFetch()), + provideClientHydration(withEventReplay()), + provideTanStackQuery(createQueryClient, withDevtools()), + ], +} diff --git a/examples/angular/ssr/src/app/app.routes.server.ts b/examples/angular/ssr/src/app/app.routes.server.ts new file mode 100644 index 00000000000..09fcfa3cc95 --- /dev/null +++ b/examples/angular/ssr/src/app/app.routes.server.ts @@ -0,0 +1,9 @@ +import { RenderMode } from '@angular/ssr' +import type { ServerRoute } from '@angular/ssr' + +export const serverRoutes: Array = [ + { + path: '**', + renderMode: RenderMode.Server, + }, +] diff --git a/examples/angular/ssr/src/app/components/posts.component.ts b/examples/angular/ssr/src/app/components/posts.component.ts new file mode 100644 index 00000000000..e9b13754d57 --- /dev/null +++ b/examples/angular/ssr/src/app/components/posts.component.ts @@ -0,0 +1,70 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core' +import { injectQuery } from '@tanstack/angular-query' +import { lastValueFrom } from 'rxjs' +import { PostsService } from '../services/posts.service' + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'posts', + template: ` + @if (postsQuery.isPending()) { +

Loading posts...

+ } @else if (postsQuery.isError()) { +

Failed to load posts.

+ } @else { +
+ @for (post of postsQuery.data(); track post.id) { +
+

Post #{{ post.id }}

+

{{ post.title }}

+

{{ post.body }}

+
+ } +
+ } + `, + styles: ` + .grid { + display: grid; + gap: 16px; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + } + + .card { + padding: 20px; + border: 1px solid #eadfcb; + border-radius: 18px; + background: #fffdf8; + box-shadow: 0 12px 30px rgba(123, 88, 31, 0.08); + } + + .meta { + margin: 0 0 10px; + font-size: 12px; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + color: #8b5e34; + } + + h2 { + margin: 0 0 10px; + font-size: 1.1rem; + line-height: 1.3; + } + + p { + margin: 0; + line-height: 1.5; + color: #374151; + } + `, +}) +export class PostsComponent { + readonly #postsService = inject(PostsService) + + readonly postsQuery = injectQuery(() => ({ + queryKey: ['posts'], + queryFn: () => lastValueFrom(this.#postsService.allPosts$()), + })) +} diff --git a/examples/angular/ssr/src/app/query-client.ts b/examples/angular/ssr/src/app/query-client.ts new file mode 100644 index 00000000000..16bf58ab9ca --- /dev/null +++ b/examples/angular/ssr/src/app/query-client.ts @@ -0,0 +1,19 @@ +import { isPlatformServer } from '@angular/common' +import { PLATFORM_ID, inject } from '@angular/core' +import { QueryClient } from '@tanstack/angular-query' + +export const SHARED_QUERY_DEFAULTS = { + staleTime: 1000 * 30, + gcTime: 1000 * 60 * 60 * 24, +} as const + +export function createQueryClient() { + return new QueryClient({ + defaultOptions: { + queries: { + ...SHARED_QUERY_DEFAULTS, + ...(isPlatformServer(inject(PLATFORM_ID)) ? { retry: false } : {}), + }, + }, + }) +} diff --git a/examples/angular/ssr/src/app/services/posts.service.ts b/examples/angular/ssr/src/app/services/posts.service.ts new file mode 100644 index 00000000000..a650707f686 --- /dev/null +++ b/examples/angular/ssr/src/app/services/posts.service.ts @@ -0,0 +1,53 @@ +import { Injectable } from '@angular/core' +import { of, tap } from 'rxjs' +import { delay } from 'rxjs/operators' + +@Injectable({ + providedIn: 'root', +}) +export class PostsService { + allPosts$ = () => + of(posts).pipe( + tap(() => console.log('fetching posts')), + delay(50), + ) +} + +export interface Post { + id: number + title: string + body: string +} + +const posts: Array = [ + { + id: 1, + title: 'Render on the server', + body: 'The initial HTML is produced by Angular SSR before the browser bootstraps the app.', + }, + { + id: 2, + title: 'Hydrate on the client', + body: 'Angular reuses the rendered DOM and turns it into a live client application.', + }, + { + id: 3, + title: 'Query on both sides', + body: 'TanStack Query resolves during server rendering, then transfers the hydrated cache to the browser.', + }, + { + id: 4, + title: 'No API needed', + body: 'This example uses a deterministic in-memory data source so the SSR example works without external network access.', + }, + { + id: 5, + title: 'Keep the setup small', + body: 'Only the Angular CLI SSR pieces remain: main.server.ts, server.ts and the server application config.', + }, + { + id: 6, + title: 'Match the other examples', + body: 'The rest of the app keeps the same lightweight structure as the existing Angular examples in this repo.', + }, +] diff --git a/examples/angular/ssr/src/index.html b/examples/angular/ssr/src/index.html new file mode 100644 index 00000000000..ab7606ebbf6 --- /dev/null +++ b/examples/angular/ssr/src/index.html @@ -0,0 +1,12 @@ + + + + + TanStack Query Angular SSR Example + + + + + + + diff --git a/examples/angular/ssr/src/main.server.ts b/examples/angular/ssr/src/main.server.ts new file mode 100644 index 00000000000..df44a7c47b7 --- /dev/null +++ b/examples/angular/ssr/src/main.server.ts @@ -0,0 +1,11 @@ +import { + bootstrapApplication, + type BootstrapContext, +} from '@angular/platform-browser' +import { serverConfig } from './app/app.config.server' +import { SsrExampleComponent } from './app/app.component' + +const bootstrap = (context: BootstrapContext) => + bootstrapApplication(SsrExampleComponent, serverConfig, context) + +export default bootstrap diff --git a/examples/angular/ssr/src/main.ts b/examples/angular/ssr/src/main.ts new file mode 100644 index 00000000000..f63fdacda8d --- /dev/null +++ b/examples/angular/ssr/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser' +import { appConfig } from './app/app.config' +import { SsrExampleComponent } from './app/app.component' + +bootstrapApplication(SsrExampleComponent, appConfig).catch((err) => + console.error(err), +) diff --git a/examples/angular/ssr/src/server.ts b/examples/angular/ssr/src/server.ts new file mode 100644 index 00000000000..db670c6eb0d --- /dev/null +++ b/examples/angular/ssr/src/server.ts @@ -0,0 +1,43 @@ +import { + AngularNodeAppEngine, + createNodeRequestHandler, + isMainModule, + writeResponseToNodeResponse, +} from '@angular/ssr/node' +import express from 'express' +import { join } from 'node:path' + +const browserDistFolder = join(import.meta.dirname, '../browser') + +const app = express() +const angularApp = new AngularNodeAppEngine() + +app.use( + express.static(browserDistFolder, { + maxAge: '1y', + index: false, + redirect: false, + }), +) + +app.use((req, res, next) => { + angularApp + .handle(req) + .then((response) => + response ? writeResponseToNodeResponse(response, res) : next(), + ) + .catch(next) +}) + +if (isMainModule(import.meta.url)) { + const port = process.env['PORT'] || 4000 + app.listen(port, (error) => { + if (error) { + throw error + } + + console.log(`Node Express server listening on http://localhost:${port}`) + }) +} + +export const reqHandler = createNodeRequestHandler(app) diff --git a/examples/angular/ssr/src/styles.css b/examples/angular/ssr/src/styles.css new file mode 100644 index 00000000000..6718c269c49 --- /dev/null +++ b/examples/angular/ssr/src/styles.css @@ -0,0 +1,16 @@ +body { + margin: 0; + font-family: + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + sans-serif; + background: #faf8f2; + color: #1b1f23; +} + +button { + font: inherit; +} diff --git a/examples/angular/ssr/tsconfig.app.json b/examples/angular/ssr/tsconfig.app.json new file mode 100644 index 00000000000..00e9b764198 --- /dev/null +++ b/examples/angular/ssr/tsconfig.app.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": ["node"] + }, + "include": ["src/**/*.ts"] +} diff --git a/examples/angular/ssr/tsconfig.json b/examples/angular/ssr/tsconfig.json new file mode 100644 index 00000000000..5aa05d2d231 --- /dev/null +++ b/examples/angular/ssr/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "isolatedModules": true, + "experimentalDecorators": true, + "importHelpers": true, + "target": "ES2022", + "module": "preserve" + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "typeCheckHostBindings": true, + "strictTemplates": true + }, + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/examples/angular/to-resource-signal-forms/README.md b/examples/angular/to-resource-signal-forms/README.md new file mode 100644 index 00000000000..e6c8b844c2f --- /dev/null +++ b/examples/angular/to-resource-signal-forms/README.md @@ -0,0 +1,21 @@ +# TanStack Query Angular `toResource` with Signal Forms example + +This example uses Angular Signal Forms' `validateAsync` with a Resource created +from `injectQuery` and `toResource`. The username check is cached by its query +key, debounced while typing, and cancelled when the value changes. The example +also adds an invite-code field dynamically, giving it its own async validator, +and includes a button that calls Signal Forms' `reloadValidation()` API. The +invite-code validator is applied with `applyEach`, so its Resource factory is +created only when an invite-code item is added to the form array. Query keys and +request options live in `ValidationQueriesService`; the validators spread those +options and add `enabled` based on the current field value. +Submitting the form runs a mock `injectMutation`, disables the submit button while it is pending, +and displays the variables passed to the mutation. + +This example intentionally uses Angular 22 because Signal Forms' `validateAsync` +API is stable starting in Angular 22. + +To run this example: + +- `pnpm install` +- `pnpm start` diff --git a/examples/angular/to-resource-signal-forms/angular.json b/examples/angular/to-resource-signal-forms/angular.json new file mode 100644 index 00000000000..8b7a5fde388 --- /dev/null +++ b/examples/angular/to-resource-signal-forms/angular.json @@ -0,0 +1,58 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "cli": { "packageManager": "pnpm", "analytics": false }, + "projects": { + "to-resource-signal-forms": { + "projectType": "application", + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular/build:application", + "options": { + "outputPath": "dist/to-resource-signal-forms", + "index": "src/index.html", + "browser": "src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "tsconfig.app.json", + "assets": [], + "styles": ["src/styles.css"] + }, + "configurations": { + "production": { "outputHashing": "all" }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular/build:dev-server", + "options": { + "prebundle": { + "exclude": [ + "@angular/common", + "@angular/core", + "@angular/forms", + "@angular/platform-browser" + ] + } + }, + "configurations": { + "production": { + "buildTarget": "to-resource-signal-forms:build:production" + }, + "development": { + "buildTarget": "to-resource-signal-forms:build:development" + } + }, + "defaultConfiguration": "development" + } + } + } + } +} diff --git a/examples/angular/to-resource-signal-forms/package.json b/examples/angular/to-resource-signal-forms/package.json new file mode 100644 index 00000000000..eed160329fb --- /dev/null +++ b/examples/angular/to-resource-signal-forms/package.json @@ -0,0 +1,29 @@ +{ + "name": "@tanstack/query-example-angular-to-resource-signal-forms", + "private": true, + "type": "module", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development" + }, + "dependencies": { + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/forms": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query-devtools": "workspace:*", + "@tanstack/angular-query": "workspace:*", + "rxjs": "^7.8.2", + "tslib": "^2.8.1", + "zone.js": "0.16.1" + }, + "devDependencies": { + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" + } +} diff --git a/examples/angular/to-resource-signal-forms/src/app/app.component.css b/examples/angular/to-resource-signal-forms/src/app/app.component.css new file mode 100644 index 00000000000..665ce6ad670 --- /dev/null +++ b/examples/angular/to-resource-signal-forms/src/app/app.component.css @@ -0,0 +1,75 @@ +:host { + display: block; +} + +main { + margin: 3rem auto; + max-width: 42rem; + padding: 0 1rem; +} + +form, +label, +.invite-code-row { + display: grid; + gap: 0.5rem; +} + +label { + max-width: 22rem; +} + +input, +button { + font: inherit; +} + +input { + padding: 0.55rem 0.7rem; +} + +button { + padding: 0.275rem 0.7rem; +} + +button { + justify-self: start; +} + +.hint { + color: #5f6368; + font-size: 0.9rem; +} + +.checking { + margin: 0; + padding: 0.2rem 0.45rem; + color: #805b00; +} + +.error { + margin: 0; + padding: 0.2rem 0.45rem; + color: #b42318; +} + +.success { + margin: 0; + padding: 0.2rem 0.45rem; + color: #067647; +} + +.invite-code-row { + grid-template-columns: minmax(0, 1fr) auto; + align-items: end; + border-left: 3px solid #d0d5dd; + padding-left: 0.75rem; +} + +.invite-code-row > button { + margin-bottom: 0; +} + +.invite-code-row > p { + grid-column: 1 / -1; +} diff --git a/examples/angular/to-resource-signal-forms/src/app/app.component.ts b/examples/angular/to-resource-signal-forms/src/app/app.component.ts new file mode 100644 index 00000000000..b4dfd78390e --- /dev/null +++ b/examples/angular/to-resource-signal-forms/src/app/app.component.ts @@ -0,0 +1,249 @@ +import { + ChangeDetectionStrategy, + Component, + inject, + signal, +} from '@angular/core' +import { + FormField, + applyEach, + form, + minLength, + required, + submit as submitForm, + validateAsync, +} from '@angular/forms/signals' +import { + injectMutation, + injectQuery, + toResource, +} from '@tanstack/angular-query' +import { ValidationQueriesService } from './validation-queries.service' + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'app-root', + imports: [FormField], + styleUrl: './app.component.css', + template: ` +
+

Username availability

+

+ Signal Forms uses a Resource backed by TanStack Query for async + validation. Try taken or any other username. +

+ +
+ + + @if (registrationForm.username().pending()) { +

Checking availability...

+ } + + @if ( + registrationForm.username().touched() && + registrationForm.username().invalid() + ) { + @for (error of registrationForm.username().errors(); track $index) { +

{{ error.message }}

+ } + } + + @if ( + registrationForm.username().touched() && + registrationForm.username().valid() + ) { +

Username is available.

+ } + +

+ Invite-code validators are added with each array item. The query + resource does not exist until an invite code is added. +

+ + + + @for ( + inviteCode of registrationForm.inviteCodes; + track $index; + let index = $index + ) { +
+ + + + + @if (inviteCode().pending()) { +

Checking invite code...

+ } + + @if (inviteCode().touched() && inviteCode().invalid()) { + @for (error of inviteCode().errors(); track $index) { +

{{ error.message }}

+ } + } + + @if (inviteCode().touched() && inviteCode().valid()) { +

Invite code is valid.

+ } +
+ } + + + + + + @if (registrationMutation.isError()) { +

Could not submit the registration.

+ } + + @if ( + registrationMutation.isSuccess() && registrationMutation.data().ok + ) { +

+ Registration accepted for + {{ registrationMutation.variables().username }}. +

+

+ Mutation variables included + {{ registrationMutation.variables().inviteCodes.length }} + invite code(s). +

+ } +
+
+ `, +}) +export class AppComponent { + private readonly queries = inject(ValidationQueriesService) + readonly model = signal({ username: '', inviteCodes: [] as Array }) + readonly registrationMutation = injectMutation(() => + this.queries.submitRegistration(), + ) + + readonly registrationForm = form(this.model, (path) => { + required(path.username, { message: 'Username is required' }) + minLength(path.username, 3, { + message: 'Username must be at least 3 characters', + }) + + validateAsync(path.username, { + debounce: 300, + params: ({ value }) => value().trim() || undefined, + factory: (username) => { + const query = injectQuery(() => { + const name = username() ?? '' + return { + ...this.queries.usernameAvailability(name), + enabled: !!name, + } + }) + + return toResource(query) + }, + onSuccess: (result) => + result.available + ? null + : { + kind: 'usernameTaken', + message: 'Username is already taken', + }, + onError: () => ({ + kind: 'usernameUnavailable', + message: 'Could not check username availability', + }), + }) + + applyEach(path.inviteCodes, (inviteCode) => { + required(inviteCode, { message: 'Invite code is required' }) + minLength(inviteCode, 3, { + message: 'Invite code must be at least 3 characters', + }) + + validateAsync(inviteCode, { + debounce: 300, + params: ({ value }) => value().trim() || undefined, + factory: (code) => { + const query = injectQuery(() => { + const value = code() ?? '' + return { + ...this.queries.inviteCodeValidation(value), + enabled: !!value, + } + }) + + return toResource(query) + }, + onSuccess: (result) => + result.valid + ? null + : { + kind: 'invalidInviteCode', + message: 'Invite code must start with TEAM-', + }, + onError: () => ({ + kind: 'inviteCodeUnavailable', + message: 'Could not check the invite code', + }), + }) + }) + }) + + addInviteCode() { + this.model.update((model) => ({ + ...model, + inviteCodes: [...model.inviteCodes, ''], + })) + } + + removeInviteCode(index: number) { + this.model.update((model) => ({ + ...model, + inviteCodes: model.inviteCodes.filter( + (_, itemIndex) => itemIndex !== index, + ), + })) + } + + async submit(event: SubmitEvent) { + event.preventDefault() + + const success = await submitForm(this.registrationForm, { + ignoreValidators: 'none', + action: async (field) => { + const result = await this.registrationMutation.mutateAsync( + field().value(), + ) + + if (!result.ok) { + return result.errors.map((error) => ({ + fieldTree: + error.fieldPath[0] === 'username' + ? this.registrationForm.username + : this.registrationForm.inviteCodes[error.fieldPath[1]], + kind: 'server', + message: error.error, + })) + } + + return undefined + }, + }) + if (success) { + this.model.set({ username: '', inviteCodes: [] }) + } + } +} diff --git a/examples/angular/to-resource-signal-forms/src/app/app.config.ts b/examples/angular/to-resource-signal-forms/src/app/app.config.ts new file mode 100644 index 00000000000..0038688124f --- /dev/null +++ b/examples/angular/to-resource-signal-forms/src/app/app.config.ts @@ -0,0 +1,7 @@ +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' +import type { ApplicationConfig } from '@angular/core' + +export const appConfig: ApplicationConfig = { + providers: [provideTanStackQuery(() => new QueryClient(), withDevtools())], +} diff --git a/examples/angular/to-resource-signal-forms/src/app/validation-queries.service.ts b/examples/angular/to-resource-signal-forms/src/app/validation-queries.service.ts new file mode 100644 index 00000000000..85d5529e666 --- /dev/null +++ b/examples/angular/to-resource-signal-forms/src/app/validation-queries.service.ts @@ -0,0 +1,89 @@ +import { Injectable } from '@angular/core' +import { mutationOptions, queryOptions } from '@tanstack/angular-query' + +export type UsernameValidation = { + available: boolean +} + +export type InviteCodeValidation = { + valid: boolean +} + +export type RegistrationData = { + username: string + inviteCodes: Array +} + +export type RegistrationMutationResult = + | { ok: true } + | { + ok: false + errors: Array<{ + fieldPath: ['username'] | ['inviteCodes', number] + error: string + }> + } + +@Injectable({ providedIn: 'root' }) +export class ValidationQueriesService { + usernameAvailability(username: string) { + return queryOptions({ + queryKey: ['username-availability', username], + gcTime: 15_000, + queryFn: async (): Promise => { + await this.delay() + return { available: username.toLowerCase() !== 'taken' } + }, + }) + } + + inviteCodeValidation(code: string) { + return queryOptions({ + queryKey: ['invite-code-validation', code], + gcTime: 15_000, + staleTime: 30_000, + queryFn: async (): Promise => { + await this.delay() + return { valid: code.toUpperCase().startsWith('TEAM-') } + }, + }) + } + + submitRegistration() { + return mutationOptions({ + gcTime: 20_000, + mutationFn: async ( + variables: RegistrationData, + ): Promise => { + await this.delay() + + const errors: Array<{ + fieldPath: ['username'] | ['inviteCodes', number] + error: string + }> = [] + + if (variables.username.toLowerCase().includes('error')) { + errors.push({ + fieldPath: ['username'], + error: 'This username cannot be registered', + }) + } + + variables.inviteCodes.forEach((inviteCode, index) => { + if (inviteCode.toLowerCase().includes('error')) { + errors.push({ + fieldPath: ['inviteCodes', index], + error: 'This invite code cannot be registered', + }) + } + }) + + return errors.length > 0 ? { ok: false, errors } : { ok: true } + }, + }) + } + + private delay() { + return new Promise((resolve) => setTimeout(resolve, 450)) + } +} diff --git a/examples/angular/to-resource-signal-forms/src/index.html b/examples/angular/to-resource-signal-forms/src/index.html new file mode 100644 index 00000000000..fac15051cbe --- /dev/null +++ b/examples/angular/to-resource-signal-forms/src/index.html @@ -0,0 +1,12 @@ + + + + + toResource with Signal Forms + + + + + + + diff --git a/examples/angular/to-resource-signal-forms/src/main.ts b/examples/angular/to-resource-signal-forms/src/main.ts new file mode 100644 index 00000000000..ef15666eff7 --- /dev/null +++ b/examples/angular/to-resource-signal-forms/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser' +import { appConfig } from './app/app.config' +import { AppComponent } from './app/app.component' + +bootstrapApplication(AppComponent, appConfig).catch((error) => + console.error(error), +) diff --git a/examples/angular/to-resource-signal-forms/src/styles.css b/examples/angular/to-resource-signal-forms/src/styles.css new file mode 100644 index 00000000000..be398679351 --- /dev/null +++ b/examples/angular/to-resource-signal-forms/src/styles.css @@ -0,0 +1,8 @@ +body { + background: #f7f7f8; + color: #202124; + font: + 16px/1.5 system-ui, + sans-serif; + margin: 0; +} diff --git a/examples/angular/to-resource-signal-forms/tsconfig.app.json b/examples/angular/to-resource-signal-forms/tsconfig.app.json new file mode 100644 index 00000000000..a7da28e8cea --- /dev/null +++ b/examples/angular/to-resource-signal-forms/tsconfig.app.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { "outDir": "./out-tsc/app", "types": [] }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"] +} diff --git a/examples/angular/to-resource-signal-forms/tsconfig.json b/examples/angular/to-resource-signal-forms/tsconfig.json new file mode 100644 index 00000000000..f42b458e4ac --- /dev/null +++ b/examples/angular/to-resource-signal-forms/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "isolatedModules": true, + "experimentalDecorators": true, + "moduleResolution": "bundler", + "importHelpers": true, + "target": "ES2022", + "module": "preserve", + "lib": ["ES2022", "dom"] + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/integrations/angular-cli-20/package.json b/integrations/angular-cli-20/package.json index 86aac62200c..0fd7f49b12d 100644 --- a/integrations/angular-cli-20/package.json +++ b/integrations/angular-cli-20/package.json @@ -8,21 +8,22 @@ "watch": "ng build --watch --configuration development" }, "dependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/forms": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@angular/router": "^20.0.0", - "@tanstack/angular-query-experimental": "^5.103.2", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/forms": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@angular/router": "^22.0.0", + "@tanstack/angular-query": "workspace:*", + "@tanstack/angular-query-devtools": "workspace:*", "rxjs": "~7.8.0", "tslib": "^2.3.0", - "zone.js": "~0.15.0" + "zone.js": "~0.16.0" }, "devDependencies": { - "@angular/build": "^20.0.0", - "@angular/cli": "^20.0.0", - "@angular/compiler-cli": "^20.0.0", - "typescript": "~5.8.2" + "@angular/build": "^22.0.0", + "@angular/cli": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "typescript": "6.0.3" } } diff --git a/integrations/angular-cli-20/src/app/app.config.ts b/integrations/angular-cli-20/src/app/app.config.ts index 8383c690fd7..9e46b692246 100644 --- a/integrations/angular-cli-20/src/app/app.config.ts +++ b/integrations/angular-cli-20/src/app/app.config.ts @@ -3,15 +3,13 @@ import { provideBrowserGlobalErrorListeners, provideZonelessChangeDetection, } from '@angular/core' -import { - provideTanStackQuery, - QueryClient, -} from '@tanstack/angular-query-experimental' +import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' export const appConfig: ApplicationConfig = { providers: [ provideBrowserGlobalErrorListeners(), provideZonelessChangeDetection(), - provideTanStackQuery(new QueryClient()), + provideTanStackQuery(() => new QueryClient(), withDevtools()), ], } diff --git a/integrations/angular-cli-20/src/app/app.ts b/integrations/angular-cli-20/src/app/app.ts index a0f0a34ba44..b918333c774 100644 --- a/integrations/angular-cli-20/src/app/app.ts +++ b/integrations/angular-cli-20/src/app/app.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core' -import { injectQuery } from '@tanstack/angular-query-experimental' +import { injectQuery } from '@tanstack/angular-query' @Component({ selector: 'app-root', diff --git a/packages/angular-query-devtools/README.md b/packages/angular-query-devtools/README.md new file mode 100644 index 00000000000..1981576c796 --- /dev/null +++ b/packages/angular-query-devtools/README.md @@ -0,0 +1,23 @@ +# @tanstack/angular-query-devtools + +Developer tools for `@tanstack/angular-query`. + +```sh +pnpm add -D @tanstack/angular-query-devtools +``` + +```ts +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withDevtools } from '@tanstack/angular-query-devtools' + +export const appConfig: ApplicationConfig = { + providers: [provideTanStackQuery(() => new QueryClient(), withDevtools())], +} +``` + +The default import resolves to a stub in production builds. To opt in to the +real implementation in production, import `withDevtools` from +`@tanstack/angular-query-devtools/production`. + +The options callback runs inside an Angular injection context, so it can call +`inject()` and read signals directly. diff --git a/packages/angular-query-devtools/package.json b/packages/angular-query-devtools/package.json new file mode 100644 index 00000000000..7055d656b93 --- /dev/null +++ b/packages/angular-query-devtools/package.json @@ -0,0 +1,113 @@ +{ + "name": "@tanstack/angular-query-devtools", + "version": "4.0.0", + "description": "Developer tools to interact with and visualize the TanStack Angular Query cache", + "author": "Arnoud de Vries", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/TanStack/query.git", + "directory": "packages/angular-query-devtools" + }, + "homepage": "https://tanstack.com/query", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "keywords": [ + "angular", + "angular query", + "devtools", + "tanstack" + ], + "scripts": { + "clean": "premove ./dist ./coverage ./dist-ts", + "compile": "tsc --build", + "test:eslint": "eslint --concurrency=auto ./src", + "test:types": "npm-run-all --serial test:types:*", + "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js --build", + "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js --build", + "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --build", + "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js --build", + "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js --build", + "test:types:tscurrent": "tsc --build", + "test:types:ts60": "node ../../node_modules/typescript60/lib/tsc.js --build", + "test:lib": "vitest", + "test:lib:dev": "pnpm run test:lib --watch", + "test:build": "trap 'premove ./dist/*.tgz' EXIT; pnpm pack && publint ./dist/*.tgz --strict && attw ./dist/*.tgz --ignore-rules cjs-resolves-to-esm", + "build": "vite build", + "prepack": "node scripts/prepack.js" + }, + "type": "module", + "types": "dist/index.d.ts", + "module": "dist/index.mjs", + "exports": { + ".": { + "@tanstack/custom-condition": "./src/index.ts", + "types": "./dist/index.d.ts", + "development": "./dist/index.mjs", + "default": "./dist/stub.mjs" + }, + "./package.json": "./package.json", + "./stub": { + "types": "./dist/stub.d.ts", + "default": "./dist/stub.mjs" + }, + "./production": { + "types": "./dist/production/index.d.ts", + "default": "./dist/index.mjs" + }, + "./devtools-panel": { + "@tanstack/custom-condition": "./src/devtools-panel/index.ts", + "types": "./dist/devtools-panel/index.d.ts", + "development": "./dist/devtools-panel/index.mjs", + "default": "./dist/devtools-panel/stub.mjs" + }, + "./devtools-panel/production": { + "types": "./dist/devtools-panel/production/index.d.ts", + "default": "./dist/devtools-panel/index.mjs" + }, + "./devtools-panel/stub": { + "types": "./dist/devtools-panel/stub.d.ts", + "default": "./dist/devtools-panel/stub.mjs" + } + }, + "sideEffects": false, + "files": [ + "**/*.d.ts", + "**/*.mjs", + "**/*.mjs.map" + ], + "dependencies": { + "@tanstack/query-core": "workspace:*", + "@tanstack/query-devtools": "workspace:*" + }, + "devDependencies": { + "@analogjs/vite-plugin-angular": "^2.3.1", + "@angular/build": "^22.0.0", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@tanstack/angular-query": "workspace:*", + "@testing-library/jest-dom": "^6.8.0", + "npm-run-all2": "^5.0.0", + "rxjs": "^7.8.2", + "typescript": "5.9.3", + "vite-plugin-dts": "4.2.3", + "vite-plugin-externalize-deps": "^0.9.0", + "vite-tsconfig-paths": "^5.1.4", + "vitest": "^4.0.18", + "zone.js": "^0.16.0" + }, + "peerDependencies": { + "@angular/common": ">=22.0.0", + "@angular/core": ">=22.0.0", + "@tanstack/angular-query": "workspace:^" + }, + "publishConfig": { + "directory": "dist", + "linkDirectory": false + } +} diff --git a/packages/angular-query-experimental/scripts/prepack.js b/packages/angular-query-devtools/scripts/prepack.js similarity index 89% rename from packages/angular-query-experimental/scripts/prepack.js rename to packages/angular-query-devtools/scripts/prepack.js index bf4bef0cc75..b01eaa65a0d 100644 --- a/packages/angular-query-experimental/scripts/prepack.js +++ b/packages/angular-query-devtools/scripts/prepack.js @@ -50,14 +50,16 @@ function replaceDist(filePath) { */ function processExports(exports) { return Object.fromEntries( - Object.entries(exports).map(([key, value]) => [ - key, - typeof value === 'string' - ? replaceDist(value) - : typeof value === 'object' && value !== null - ? processExports(value) - : value, - ]), + Object.entries(exports) + .filter(([key]) => key !== '@tanstack/custom-condition') + .map(([key, value]) => [ + key, + typeof value === 'string' + ? replaceDist(value) + : typeof value === 'object' && value !== null + ? processExports(value) + : value, + ]), ) } diff --git a/packages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.ts b/packages/angular-query-devtools/src/__tests__/inject-devtools-panel.test.ts similarity index 66% rename from packages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.ts rename to packages/angular-query-devtools/src/__tests__/inject-devtools-panel.test.ts index 3a1fc4bca89..35ec2ab7dae 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.ts +++ b/packages/angular-query-devtools/src/__tests__/inject-devtools-panel.test.ts @@ -1,13 +1,9 @@ -import { - ElementRef, - provideZonelessChangeDetection, - signal, -} from '@angular/core' +import { ApplicationRef, ElementRef, signal } from '@angular/core' import { TestBed } from '@angular/core/testing' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { QueryClient } from '@tanstack/query-core' -import { provideTanStackQuery } from '../providers' import { injectDevtoolsPanel } from '../devtools-panel' +import { setupTanStackQueryTestBed } from './test-utils' const mockDevtoolsPanelInstance = { mount: vi.fn(), @@ -45,12 +41,8 @@ describe('injectDevtoolsPanel', () => { vi.clearAllMocks() queryClient = new QueryClient() mockElementRef = new ElementRef(document.createElement('div')) - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), - { provide: ElementRef, useValue: signal(mockElementRef) }, - ], + setupTanStackQueryTestBed(queryClient, { + providers: [{ provide: ElementRef, useValue: signal(mockElementRef) }], }) }) @@ -77,7 +69,7 @@ describe('injectDevtoolsPanel', () => { })) }) - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() await waitForDevtoolsToBeCreated() @@ -91,17 +83,53 @@ describe('injectDevtoolsPanel', () => { })) }) - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() + + await waitForDevtoolsToBeCreated() + + result.destroy() + + expect(mockDevtoolsPanelInstance.unmount).toHaveBeenCalledTimes(1) + }) + it('should stop reacting after it is manually destroyed', async () => { + const hostElement = signal(mockElementRef) + const result = TestBed.runInInjectionContext(() => + injectDevtoolsPanel(() => ({ + hostElement: hostElement(), + })), + ) + + await TestBed.inject(ApplicationRef).whenStable() await waitForDevtoolsToBeCreated() result.destroy() + hostElement.set(undefined) + hostElement.set(mockElementRef) + await TestBed.inject(ApplicationRef).whenStable() + expect(mocks.mockTanstackQueryDevtoolsPanel).toHaveBeenCalledTimes(1) + expect(mockDevtoolsPanelInstance.mount).toHaveBeenCalledTimes(1) expect(mockDevtoolsPanelInstance.unmount).toHaveBeenCalledTimes(1) }) + it('should not mount when destroyed while the devtools import is pending', async () => { + const result = TestBed.runInInjectionContext(() => + injectDevtoolsPanel(() => ({ + hostElement: mockElementRef, + })), + ) + + TestBed.tick() + result.destroy() + await TestBed.inject(ApplicationRef).whenStable() + + expect(mocks.mockTanstackQueryDevtoolsPanel).not.toHaveBeenCalled() + expect(mockDevtoolsPanelInstance.mount).not.toHaveBeenCalled() + }) + it('should destroy TanstackQueryDevtoolsPanel when hostElement is removed', async () => { - const hostElement = signal(mockElementRef) + const hostElement = signal(mockElementRef) TestBed.runInInjectionContext(() => { return injectDevtoolsPanel(() => ({ @@ -109,15 +137,15 @@ describe('injectDevtoolsPanel', () => { })) }) - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() await waitForDevtoolsToBeCreated() expect(mockDevtoolsPanelInstance.unmount).toHaveBeenCalledTimes(0) - hostElement.set(null as unknown as ElementRef) + hostElement.set(null) - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsPanelInstance.unmount).toHaveBeenCalledTimes(1) }) @@ -132,7 +160,7 @@ describe('injectDevtoolsPanel', () => { })) }) - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() await waitForDevtoolsToBeCreated() @@ -140,7 +168,7 @@ describe('injectDevtoolsPanel', () => { client.set(new QueryClient()) - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsPanelInstance.setClient).toHaveBeenCalledTimes(1) }) @@ -155,7 +183,7 @@ describe('injectDevtoolsPanel', () => { })) }) - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() await waitForDevtoolsToBeCreated() @@ -163,7 +191,7 @@ describe('injectDevtoolsPanel', () => { errorTypes.set([]) - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsPanelInstance.setErrorTypes).toHaveBeenCalledTimes(1) }) @@ -181,7 +209,7 @@ describe('injectDevtoolsPanel', () => { })) }) - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() await waitForDevtoolsToBeCreated() @@ -189,7 +217,7 @@ describe('injectDevtoolsPanel', () => { onClose.set(functionB) - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsPanelInstance.setOnClose).toHaveBeenCalledTimes(1) }) diff --git a/packages/angular-query-devtools/src/__tests__/test-utils.ts b/packages/angular-query-devtools/src/__tests__/test-utils.ts new file mode 100644 index 00000000000..88e2296713a --- /dev/null +++ b/packages/angular-query-devtools/src/__tests__/test-utils.ts @@ -0,0 +1,19 @@ +import { provideZonelessChangeDetection } from '@angular/core' +import { TestBed } from '@angular/core/testing' +import { provideTanStackQuery } from '@tanstack/angular-query' +import type { QueryClient } from '@tanstack/query-core' +import type { EnvironmentProviders, Provider } from '@angular/core' + +export function setupTanStackQueryTestBed( + queryClient: QueryClient, + options: { providers?: Array } = {}, +) { + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideZonelessChangeDetection(), + provideTanStackQuery(() => queryClient), + ...(options.providers ?? []), + ], + }) +} diff --git a/packages/angular-query-experimental/src/__tests__/with-devtools.test.ts b/packages/angular-query-devtools/src/__tests__/with-devtools.test.ts similarity index 68% rename from packages/angular-query-experimental/src/__tests__/with-devtools.test.ts rename to packages/angular-query-devtools/src/__tests__/with-devtools.test.ts index 47ce1173440..264c1a1752e 100644 --- a/packages/angular-query-experimental/src/__tests__/with-devtools.test.ts +++ b/packages/angular-query-devtools/src/__tests__/with-devtools.test.ts @@ -2,41 +2,47 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { QueryClient } from '@tanstack/query-core' import { TestBed } from '@angular/core/testing' import { + ApplicationRef, ENVIRONMENT_INITIALIZER, EnvironmentInjector, InjectionToken, PLATFORM_ID, createEnvironmentInjector, + inject, isDevMode, provideZonelessChangeDetection, signal, } from '@angular/core' -import { provideTanStackQuery } from '../providers' -import { withDevtools } from '../devtools' +import { provideTanStackQuery } from '@tanstack/angular-query' +import { getQueryFeatureProviders } from '@tanstack/angular-query/internal' +import { withDevtools } from '../index' import type { DevtoolsButtonPosition, DevtoolsErrorType, DevtoolsPosition, Theme, } from '@tanstack/query-devtools' -import type { DevtoolsOptions } from '../devtools' - -const mockDevtoolsInstance = { - mount: vi.fn(), - unmount: vi.fn(), - setClient: vi.fn(), - setPosition: vi.fn(), - setErrorTypes: vi.fn(), - setButtonPosition: vi.fn(), - setInitialIsOpen: vi.fn(), - setTheme: vi.fn(), -} - -function MockTanstackQueryDevtools() { - return mockDevtoolsInstance -} +import type { DevtoolsOptions } from '../types' + +const { mockDevtoolsInstance, mockTanstackQueryDevtools } = vi.hoisted(() => { + const instance = { + mount: vi.fn(), + unmount: vi.fn(), + setClient: vi.fn(), + setPosition: vi.fn(), + setErrorTypes: vi.fn(), + setButtonPosition: vi.fn(), + setInitialIsOpen: vi.fn(), + setTheme: vi.fn(), + } -const mockTanstackQueryDevtools = vi.fn(MockTanstackQueryDevtools) + return { + mockDevtoolsInstance: instance, + mockTanstackQueryDevtools: vi.fn(function MockTanstackQueryDevtools() { + return instance + }), + } +}) vi.mock('@tanstack/query-devtools', () => ({ TanstackQueryDevtools: mockTanstackQueryDevtools, @@ -55,13 +61,11 @@ const mockIsDevMode = vi.mocked(isDevMode) describe('withDevtools feature', () => { beforeEach(() => { vi.clearAllMocks() - vi.useFakeTimers() }) afterEach(() => { vi.restoreAllMocks() TestBed.resetTestingModule() - vi.useRealTimers() }) it.each([ @@ -123,7 +127,7 @@ describe('withDevtools feature', () => { const providers = [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), loadDevtools !== undefined ? withDevtools( () => @@ -140,54 +144,22 @@ describe('withDevtools feature', () => { }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) - TestBed.tick() - await vi.dynamicImportSettled() - TestBed.tick() - await vi.dynamicImportSettled() + expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1) + + await TestBed.inject(ApplicationRef).whenStable() - expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes( - expectedCalled ? 1 : 0, - ) expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes( expectedCalled ? 1 : 0, ) }, ) - it("should throw 'No QueryClient found' when 'loadDevtools' is 'true' and no 'QueryClient' is provided", async () => { - const consoleErrorSpy = vi - .spyOn(console, 'error') - .mockImplementation(() => undefined) - - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - withDevtools(() => ({ - loadDevtools: true, - })).ɵproviders, - ], - }) - - TestBed.inject(ENVIRONMENT_INITIALIZER) - TestBed.tick() - await vi.dynamicImportSettled() - - expect(mockTanstackQueryDevtools).not.toHaveBeenCalled() - expect(consoleErrorSpy).toHaveBeenCalledWith( - 'Install @tanstack/query-devtools or reinstall without --omit=optional.', - expect.objectContaining({ message: 'No QueryClient found' }), - ) - - consoleErrorSpy.mockRestore() - }) - it('should not continue loading devtools after injector is destroyed', async () => { TestBed.configureTestingModule({ providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ loadDevtools: true, })), @@ -195,13 +167,15 @@ describe('withDevtools feature', () => { ], }) + const app = TestBed.inject(ApplicationRef) TestBed.inject(ENVIRONMENT_INITIALIZER) + const stable = app.whenStable() // Destroys injector TestBed.resetTestingModule() - await vi.advanceTimersByTimeAsync(0) - await vi.dynamicImportSettled() + await stable - expect(mockTanstackQueryDevtools).not.toHaveBeenCalled() + expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1) + expect(mockDevtoolsInstance.mount).not.toHaveBeenCalled() }) it('should not create devtools again when already provided', async () => { @@ -209,7 +183,7 @@ describe('withDevtools feature', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ loadDevtools: true, })), @@ -218,8 +192,7 @@ describe('withDevtools feature', () => { }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) - await vi.dynamicImportSettled() + await TestBed.inject(ApplicationRef).whenStable() expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1) @@ -227,15 +200,17 @@ describe('withDevtools feature', () => { createEnvironmentInjector( [ - withDevtools(() => ({ - loadDevtools: true, - })).ɵproviders, + getQueryFeatureProviders( + withDevtools(() => ({ + loadDevtools: true, + })), + ), ], injector, ) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) + await TestBed.inject(ApplicationRef).whenStable() expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1) }) @@ -249,7 +224,7 @@ describe('withDevtools feature', () => { }, provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ loadDevtools: true, })), @@ -258,7 +233,7 @@ describe('withDevtools feature', () => { }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.runAllTimersAsync() + await TestBed.inject(ApplicationRef).whenStable() expect(mockTanstackQueryDevtools).not.toHaveBeenCalled() }) @@ -270,20 +245,17 @@ describe('withDevtools feature', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ loadDevtools: true, - errorTypes: errorTypes(), + errorTypes, })), ), ], }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) - await vi.dynamicImportSettled() - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setErrorTypes).toHaveBeenCalledTimes(0) @@ -295,8 +267,7 @@ describe('withDevtools feature', () => { ] errorTypes.set(newErrorTypes) - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setErrorTypes).toHaveBeenCalledTimes(1) expect(mockDevtoolsInstance.setErrorTypes).toHaveBeenCalledWith( @@ -311,27 +282,23 @@ describe('withDevtools feature', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ loadDevtools: true, - client: client(), + client, })), ), ], }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) - await vi.dynamicImportSettled() - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setClient).toHaveBeenCalledTimes(0) const newClient = new QueryClient() client.set(newClient) - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setClient).toHaveBeenCalledTimes(1) expect(mockDevtoolsInstance.setClient).toHaveBeenCalledWith(newClient) @@ -344,26 +311,22 @@ describe('withDevtools feature', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ loadDevtools: true, - position: position(), + position, })), ), ], }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) - await vi.dynamicImportSettled() - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setPosition).toHaveBeenCalledTimes(0) position.set('left') - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setPosition).toHaveBeenCalledTimes(1) expect(mockDevtoolsInstance.setPosition).toHaveBeenCalledWith('left') @@ -376,26 +339,22 @@ describe('withDevtools feature', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ loadDevtools: true, - buttonPosition: buttonPosition(), + buttonPosition, })), ), ], }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) - await vi.dynamicImportSettled() - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setButtonPosition).toHaveBeenCalledTimes(0) buttonPosition.set('bottom-right') - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setButtonPosition).toHaveBeenCalledTimes(1) expect(mockDevtoolsInstance.setButtonPosition).toHaveBeenCalledWith( @@ -410,26 +369,22 @@ describe('withDevtools feature', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ loadDevtools: true, - initialIsOpen: initialIsOpen(), + initialIsOpen, })), ), ], }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) - await vi.dynamicImportSettled() - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setInitialIsOpen).toHaveBeenCalledTimes(0) initialIsOpen.set(true) - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setInitialIsOpen).toHaveBeenCalledTimes(1) expect(mockDevtoolsInstance.setInitialIsOpen).toHaveBeenCalledWith(true) @@ -442,31 +397,59 @@ describe('withDevtools feature', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ loadDevtools: true, - theme: theme(), + theme, })), ), ], }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) - await vi.dynamicImportSettled() - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setTheme).toHaveBeenCalledTimes(0) theme.set('dark') - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setTheme).toHaveBeenCalledTimes(1) expect(mockDevtoolsInstance.setTheme).toHaveBeenCalledWith('dark') }) + it('should pass construction-only options to the devtools', async () => { + const shadowDOMTarget = document + .createElement('div') + .attachShadow({ mode: 'open' }) + + TestBed.configureTestingModule({ + providers: [ + provideZonelessChangeDetection(), + provideTanStackQuery( + () => new QueryClient(), + withDevtools(() => ({ + loadDevtools: true, + styleNonce: 'nonce', + shadowDOMTarget, + hideDisabledQueries: true, + })), + ), + ], + }) + + TestBed.inject(ENVIRONMENT_INITIALIZER) + await TestBed.inject(ApplicationRef).whenStable() + + expect(mockTanstackQueryDevtools).toHaveBeenCalledWith( + expect.objectContaining({ + styleNonce: 'nonce', + shadowDOMTarget, + hideDisabledQueries: true, + }), + ) + }) + it('should destroy devtools', async () => { const loadDevtools = signal(true) @@ -474,24 +457,22 @@ describe('withDevtools feature', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ - loadDevtools: loadDevtools(), + loadDevtools, })), ), ], }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) - await vi.dynamicImportSettled() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(1) expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(0) loadDevtools.set(false) - - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(1) }) @@ -501,7 +482,7 @@ describe('withDevtools feature', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ loadDevtools: true, })), @@ -510,9 +491,7 @@ describe('withDevtools feature', () => { }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) - TestBed.tick() - await vi.dynamicImportSettled() + await TestBed.inject(ApplicationRef).whenStable() expect(mockTanstackQueryDevtools).toHaveBeenCalled() expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(1) @@ -531,107 +510,89 @@ describe('withDevtools feature', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - new QueryClient(), + () => new QueryClient(), withDevtools(() => ({ - loadDevtools: loadDevtools(), + loadDevtools, })), ), ], }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) + await TestBed.inject(ApplicationRef).whenStable() - expect(mockTanstackQueryDevtools).not.toHaveBeenCalled() + expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1) expect(mockDevtoolsInstance.mount).not.toHaveBeenCalled() loadDevtools.set(true) - TestBed.tick() - await vi.dynamicImportSettled() + await TestBed.inject(ApplicationRef).whenStable() - expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1) expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(1) expect(mockDevtoolsInstance.unmount).not.toHaveBeenCalled() loadDevtools.set(false) - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(1) expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(1) loadDevtools.set(true) - TestBed.tick() - await vi.dynamicImportSettled() + await TestBed.inject(ApplicationRef).whenStable() // Should remount (mount called twice now) expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(2) expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(1) }) - describe('deps parameter', () => { - it('should inject dependencies and pass them to withDevtoolsFn in correct order', async () => { - const mockService1 = { value: 'service1' } - const mockService2 = { value: 'service2' } - const mockService1Token = new InjectionToken('MockService1') - const mockService2Token = new InjectionToken('MockService2') - const withDevtoolsFn = vi.fn().mockReturnValue({ loadDevtools: true }) - - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - { - provide: mockService1Token, - useValue: mockService1, - }, - { - provide: mockService2Token, - useValue: mockService2, - }, - provideTanStackQuery( - new QueryClient(), - withDevtools(withDevtoolsFn, { - deps: [mockService1Token, mockService2Token], - }), - ), - ], + describe('injection context', () => { + it('should inject dependencies directly in the callback', async () => { + const firstService = { value: 'first' } + const secondService = { value: 'second' } + const firstServiceToken = new InjectionToken('FirstService') + const secondServiceToken = new InjectionToken('SecondService') + const withDevtoolsFn = vi.fn(() => { + const first = inject(firstServiceToken) + const second = inject(secondServiceToken) + + return { + loadDevtools: true, + initialIsOpen: first === firstService && second === secondService, + } }) - TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) - - expect(withDevtoolsFn).toHaveBeenCalledWith(mockService1, mockService2) - }) - - it('should work with empty deps array', async () => { - const withDevtoolsFn = vi.fn().mockReturnValue({ loadDevtools: true }) - TestBed.configureTestingModule({ providers: [ provideZonelessChangeDetection(), + { provide: firstServiceToken, useValue: firstService }, + { provide: secondServiceToken, useValue: secondService }, provideTanStackQuery( - new QueryClient(), - withDevtools(withDevtoolsFn, { - deps: [], - }), + () => new QueryClient(), + withDevtools(withDevtoolsFn), ), ], }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) + await TestBed.inject(ApplicationRef).whenStable() - expect(withDevtoolsFn).toHaveBeenCalledWith() + expect(withDevtoolsFn).toHaveBeenCalled() + expect(mockTanstackQueryDevtools).toHaveBeenCalledWith( + expect.objectContaining({ initialIsOpen: true }), + ) }) - it('should reactively update when injected services change', async () => { + it('should reactively update when an injected service changes', async () => { class ReactiveService { enabled = signal(false) position = signal('bottom') } - const withDevtoolsFn = (service: ReactiveService) => ({ - loadDevtools: service.enabled(), - position: service.position(), + const withDevtoolsFn = vi.fn(() => { + const service = inject(ReactiveService) + return { + loadDevtools: service.enabled, + position: service.position, + } }) TestBed.configureTestingModule({ @@ -639,26 +600,23 @@ describe('withDevtools feature', () => { provideZonelessChangeDetection(), ReactiveService, provideTanStackQuery( - new QueryClient(), - withDevtools(withDevtoolsFn, { - deps: [ReactiveService], - }), + () => new QueryClient(), + withDevtools(withDevtoolsFn), ), ], }) TestBed.inject(ENVIRONMENT_INITIALIZER) - await vi.advanceTimersByTimeAsync(0) + await TestBed.inject(ApplicationRef).whenStable() const service = TestBed.inject(ReactiveService) - expect(mockTanstackQueryDevtools).not.toHaveBeenCalled() + expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1) + expect(mockDevtoolsInstance.mount).not.toHaveBeenCalled() service.enabled.set(true) - TestBed.tick() - await vi.dynamicImportSettled() + await TestBed.inject(ApplicationRef).whenStable() - expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1) expect(mockTanstackQueryDevtools).toHaveBeenCalledWith( expect.objectContaining({ position: 'bottom', @@ -666,9 +624,10 @@ describe('withDevtools feature', () => { ) service.position.set('top') - TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() expect(mockDevtoolsInstance.setPosition).toHaveBeenCalledWith('top') + expect(withDevtoolsFn).toHaveBeenCalledTimes(1) }) }) }) diff --git a/packages/angular-query-experimental/src/devtools-panel/index.ts b/packages/angular-query-devtools/src/devtools-panel/index.ts similarity index 84% rename from packages/angular-query-experimental/src/devtools-panel/index.ts rename to packages/angular-query-devtools/src/devtools-panel/index.ts index 2742a154692..b5ed79fa96a 100644 --- a/packages/angular-query-experimental/src/devtools-panel/index.ts +++ b/packages/angular-query-devtools/src/devtools-panel/index.ts @@ -1,7 +1,6 @@ export type { InjectDevtoolsPanel, DevtoolsPanelOptions, - InjectDevtoolsPanelOptions, DevtoolsPanelRef, } from './types' diff --git a/packages/angular-query-devtools/src/devtools-panel/inject-devtools-panel.ts b/packages/angular-query-devtools/src/devtools-panel/inject-devtools-panel.ts new file mode 100644 index 00000000000..c8dc50b9db8 --- /dev/null +++ b/packages/angular-query-devtools/src/devtools-panel/inject-devtools-panel.ts @@ -0,0 +1,116 @@ +import { + DestroyRef, + PLATFORM_ID, + assertInInjectionContext, + computed, + effect, + inject, + untracked, +} from '@angular/core' +import { QueryClient, onlineManager } from '@tanstack/query-core' +import { isPlatformBrowser } from '@angular/common' +import type { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools' +import type { DevtoolsPanelOptions, InjectDevtoolsPanel } from './types' + +/** + * Inject a TanStack Query devtools panel and render it in the DOM. + * + * Devtools panel allows programmatic control over the devtools, for example if you want to render + * the devtools as part of your own devtools. + * + * Consider `withDevtools` instead if you don't need this. + * @param injectDevtoolsPanelFn - A function that returns devtools panel options. + * @returns DevtoolsPanelRef + * @see https://tanstack.com/query/v5/docs/framework/angular/devtools + */ +export const injectDevtoolsPanel: InjectDevtoolsPanel = ( + injectDevtoolsPanelFn: () => DevtoolsPanelOptions, +) => { + assertInInjectionContext(injectDevtoolsPanel) + const destroyRef = inject(DestroyRef) + const isBrowser = isPlatformBrowser(inject(PLATFORM_ID)) + const injectedClient = inject(QueryClient, { optional: true }) + + const queryOptions = computed(injectDevtoolsPanelFn) + let devtools: TanstackQueryDevtoolsPanel | null = null + let optionsEffect: ReturnType | undefined + let manuallyDestroyed = false + let loadGeneration = 0 + + const unmount = () => { + devtools?.unmount() + devtools = null + } + + const destroy = () => { + if (manuallyDestroyed) return + + manuallyDestroyed = true + loadGeneration++ + optionsEffect?.destroy() + unmount() + } + + if (!isBrowser) + return { + destroy, + } + + optionsEffect = effect(() => { + const generation = ++loadGeneration + const { + client = injectedClient, + errorTypes = [], + styleNonce, + shadowDOMTarget, + onClose, + hostElement, + } = queryOptions() + + untracked(() => { + if (!client) throw new Error('No QueryClient found') + if (!devtools && hostElement) { + import('@tanstack/query-devtools') + .then((queryDevtools) => { + if ( + manuallyDestroyed || + destroyRef.destroyed || + generation !== loadGeneration + ) { + return + } + + devtools = new queryDevtools.TanstackQueryDevtoolsPanel({ + client, + queryFlavor: 'Angular Query', + version: '5', + buttonPosition: 'bottom-left', + position: 'bottom', + initialIsOpen: true, + errorTypes, + styleNonce, + shadowDOMTarget, + onClose, + onlineManager, + }) + devtools.mount(hostElement.nativeElement) + }) + .catch((error) => { + console.error('Failed to load @tanstack/query-devtools.', error) + }) + } else if (devtools && hostElement) { + devtools.setClient(client) + devtools.setErrorTypes(errorTypes) + onClose && devtools.setOnClose(onClose) + } else if (devtools && !hostElement) { + unmount() + } + }) + }) + + destroyRef.onDestroy(destroy) + + return { + destroy, + } +} diff --git a/packages/angular-query-devtools/src/devtools-panel/production/index.ts b/packages/angular-query-devtools/src/devtools-panel/production/index.ts new file mode 100644 index 00000000000..90be57a57c8 --- /dev/null +++ b/packages/angular-query-devtools/src/devtools-panel/production/index.ts @@ -0,0 +1,6 @@ +export type { + DevtoolsPanelOptions, + DevtoolsPanelRef, + InjectDevtoolsPanel, +} from '../types' +export { injectDevtoolsPanel } from '../inject-devtools-panel' diff --git a/packages/angular-query-experimental/src/devtools-panel/stub.ts b/packages/angular-query-devtools/src/devtools-panel/stub.ts similarity index 51% rename from packages/angular-query-experimental/src/devtools-panel/stub.ts rename to packages/angular-query-devtools/src/devtools-panel/stub.ts index 63e836eb5c8..7da1608a6d5 100644 --- a/packages/angular-query-experimental/src/devtools-panel/stub.ts +++ b/packages/angular-query-devtools/src/devtools-panel/stub.ts @@ -1,7 +1,17 @@ import { noop } from '@tanstack/query-core' -import type { InjectDevtoolsPanel } from './types' +import type { + DevtoolsPanelOptions, + DevtoolsPanelRef, + InjectDevtoolsPanel, +} from './types' // Stub which replaces `injectDevtoolsPanel` in production builds export const injectDevtoolsPanel: InjectDevtoolsPanel = () => ({ destroy: noop, }) + +export type { + InjectDevtoolsPanel, + DevtoolsPanelOptions, + DevtoolsPanelRef, +} diff --git a/packages/angular-query-experimental/src/devtools-panel/types.ts b/packages/angular-query-devtools/src/devtools-panel/types.ts similarity index 77% rename from packages/angular-query-experimental/src/devtools-panel/types.ts rename to packages/angular-query-devtools/src/devtools-panel/types.ts index f91974ee403..0de859d7152 100644 --- a/packages/angular-query-experimental/src/devtools-panel/types.ts +++ b/packages/angular-query-devtools/src/devtools-panel/types.ts @@ -1,16 +1,7 @@ import type { DevtoolsErrorType } from '@tanstack/query-devtools' -import type { ElementRef, Injector } from '@angular/core' +import type { ElementRef } from '@angular/core' import type { QueryClient } from '@tanstack/query-core' -export interface InjectDevtoolsPanelOptions { - /** - * The `Injector` in which to create the devtools panel. - * - * If this is not provided, the current injection context will be used instead (via `inject`). - */ - injector?: Injector -} - /** * A devtools panel, which can be manually destroyed. */ @@ -42,16 +33,15 @@ export interface DevtoolsPanelOptions { /** * Callback function that is called when the devtools panel is closed */ - onClose?: () => void + onClose?: () => unknown /** * Element where to render the devtools panel. When set to undefined or null, the devtools panel will not be created, or destroyed if existing. * If changed from undefined to a ElementRef, the devtools panel will be created. */ - hostElement?: ElementRef + hostElement?: ElementRef | null } export type InjectDevtoolsPanel = ( injectDevtoolsPanelFn: () => DevtoolsPanelOptions, - options?: InjectDevtoolsPanelOptions, ) => DevtoolsPanelRef diff --git a/packages/angular-query-devtools/src/index.ts b/packages/angular-query-devtools/src/index.ts new file mode 100644 index 00000000000..bf0f9e7b156 --- /dev/null +++ b/packages/angular-query-devtools/src/index.ts @@ -0,0 +1,3 @@ +export type { DevtoolsOptions, WithDevtools, WithDevtoolsFn } from './types' + +export { withDevtools } from './with-devtools' diff --git a/packages/angular-query-devtools/src/production/index.ts b/packages/angular-query-devtools/src/production/index.ts new file mode 100644 index 00000000000..002179bb9b2 --- /dev/null +++ b/packages/angular-query-devtools/src/production/index.ts @@ -0,0 +1,2 @@ +export type { DevtoolsOptions, WithDevtools, WithDevtoolsFn } from '../types' +export { withDevtools } from '../with-devtools' diff --git a/packages/angular-query-devtools/src/stub.ts b/packages/angular-query-devtools/src/stub.ts new file mode 100644 index 00000000000..da5031e3814 --- /dev/null +++ b/packages/angular-query-devtools/src/stub.ts @@ -0,0 +1,9 @@ +import { makeEnvironmentProviders } from '@angular/core' +import { queryFeature } from '@tanstack/angular-query/internal' +import type { DevtoolsOptions, WithDevtools, WithDevtoolsFn } from './types' + +// Stub which replaces `withDevtools` in production builds +export const withDevtools: WithDevtools = () => + queryFeature(makeEnvironmentProviders([])) + +export type { DevtoolsOptions, WithDevtools, WithDevtoolsFn } diff --git a/packages/angular-query-devtools/src/types.ts b/packages/angular-query-devtools/src/types.ts new file mode 100644 index 00000000000..5aff112b33d --- /dev/null +++ b/packages/angular-query-devtools/src/types.ts @@ -0,0 +1,92 @@ +import type { QueryClient } from '@tanstack/query-core' +import type { + DevtoolsButtonPosition, + DevtoolsErrorType, + DevtoolsPosition, + Theme, +} from '@tanstack/query-devtools' +import type { QueryFeature } from '@tanstack/angular-query' +import type { Signal } from '@angular/core' + +/** A static devtools option or an Angular signal containing that option. */ +type MaybeSignal = T | Signal + +/** + * Options for configuring the TanStack Query devtools. + */ +export interface DevtoolsOptions { + /** + * Set this true if you want the devtools to default to being open + */ + initialIsOpen?: MaybeSignal + /** + * The position of the TanStack logo to open and close the devtools panel. + * `top-left` | `top-right` | `bottom-left` | `bottom-right` | `relative` + * Defaults to `bottom-right`. + */ + buttonPosition?: MaybeSignal + /** + * The position of the TanStack Query devtools panel. + * `top` | `bottom` | `left` | `right` + * Defaults to `bottom`. + */ + position?: MaybeSignal + /** + * Custom instance of QueryClient + */ + client?: MaybeSignal + /** + * Use this so you can define custom errors that can be shown in the devtools. + */ + errorTypes?: MaybeSignal> + /** + * Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles. + */ + styleNonce?: string + /** + * Use this so you can attach the devtool's styles to a specific element in the DOM. + */ + shadowDOMTarget?: ShadowRoot + /** + * Set this to true to hide disabled queries from the devtools panel. + */ + hideDisabledQueries?: boolean + /** + * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel. + * Defaults to 'system'. + */ + theme?: MaybeSignal + + /** + * Whether the developer tools should be rendered. + * - `auto`- (Default) Renders devtools in development mode. Skips rendering in production mode. + * - `true`- Always render the devtools, regardless of the environment. + * - `false`- Never render the devtools, regardless of the environment. + * + * You can use `true` and `false` to override loading developer tools from an environment file. + * For example, a test environment might run in production mode but you may want to load developer tools. + * + * You can pass a signal to dynamically render the devtools based on a + * condition. For example, the signal could be created from an RxJS + * observable that listens for a keyboard shortcut. + * + * **Example** + * ```ts + * withDevtools(() => ({ + * initialIsOpen: true, + * loadDevtools: inject(ExampleService).loadDevtools, + * })) + * ``` + */ + loadDevtools?: MaybeSignal<'auto' | boolean> +} + +/** + * Returns devtools options. The function runs once in an Angular injection + * context, so it can call `inject()`. Pass signals as option values to make + * mutable options reactive. `styleNonce`, `shadowDOMTarget`, and + * `hideDisabledQueries` are read only when the devtools are constructed. + */ +export type WithDevtoolsFn = () => DevtoolsOptions + +export type WithDevtools = (withDevtoolsFn?: WithDevtoolsFn) => QueryFeature diff --git a/packages/angular-query-devtools/src/with-devtools.ts b/packages/angular-query-devtools/src/with-devtools.ts new file mode 100644 index 00000000000..7614b5be269 --- /dev/null +++ b/packages/angular-query-devtools/src/with-devtools.ts @@ -0,0 +1,172 @@ +import { isPlatformBrowser } from '@angular/common' +import { + DestroyRef, + InjectionToken, + PLATFORM_ID, + afterNextRender, + afterRenderEffect, + inject, + isDevMode, + isSignal, + makeEnvironmentProviders, + provideEnvironmentInitializer, +} from '@angular/core' +import { queryFeature } from '@tanstack/angular-query/internal' +import { QueryClient, onlineManager } from '@tanstack/query-core' +import { TanstackQueryDevtools } from '@tanstack/query-devtools' +import type { Signal } from '@angular/core' +import type { DevtoolsOptions, WithDevtools } from './types' + +/** + * Internal token used to prevent double providing of devtools in child injectors + */ +const DEVTOOLS_PROVIDED = new InjectionToken('', { + factory: () => ({ + isProvided: false, + }), +}) + +/** Internal token for providing devtools options. */ +const DEVTOOLS_OPTIONS = new InjectionToken('') + +function resolveOption(option: T | Signal | undefined) { + return isSignal(option) ? option() : option +} + +/** + * Enables developer tools in Angular development builds. + * + * **Example** + * + * ```ts + * export const appConfig: ApplicationConfig = { + * providers: [ + * provideTanStackQuery(() => new QueryClient(), withDevtools()), + * ] + * } + * ``` + * The devtools will be rendered in ``. + * + * If you need more control over when devtools are loaded, you can use the `loadDevtools` option. + * + * If you need more control over where devtools are rendered, consider `injectDevtoolsPanel`. This allows rendering devtools inside your own devtools for example. + * @param withDevtoolsFn - A function that returns `DevtoolsOptions`. It runs + * once in an Angular injection context and can call `inject()`. Return signals + * as individual mutable option values to update them reactively. + * @returns A set of providers for use with `provideTanStackQuery`. + * @see {@link provideTanStackQuery} + * @see {@link DevtoolsOptions} + */ +export const withDevtools: WithDevtools = (withDevtoolsFn) => + queryFeature( + makeEnvironmentProviders([ + { + provide: DEVTOOLS_OPTIONS, + useFactory: () => withDevtoolsFn?.() ?? {}, + }, + provideEnvironmentInitializer(() => { + const devtoolsProvided = inject(DEVTOOLS_PROVIDED) + if ( + !isPlatformBrowser(inject(PLATFORM_ID)) || + devtoolsProvided.isProvided + ) + return + + devtoolsProvided.isProvided = true + + const destroyRef = inject(DestroyRef) + const injectedClient = inject(QueryClient, { optional: true }) + const options = inject(DEVTOOLS_OPTIONS) + const client = resolveOption(options.client) ?? injectedClient + + if (!client) throw new Error('No QueryClient found') + + const devtools = new TanstackQueryDevtools({ + client, + queryFlavor: 'Angular Query', + version: '5', + onlineManager, + buttonPosition: resolveOption(options.buttonPosition), + position: resolveOption(options.position), + initialIsOpen: resolveOption(options.initialIsOpen), + errorTypes: resolveOption(options.errorTypes), + styleNonce: options.styleNonce, + shadowDOMTarget: options.shadowDOMTarget, + hideDisabledQueries: options.hideDisabledQueries, + theme: resolveOption(options.theme), + }) + + let renderCompleted = false + let element: HTMLElement | null = null + + const shouldMount = () => { + const loadDevtools = resolveOption(options.loadDevtools) + return typeof loadDevtools === 'boolean' ? loadDevtools : isDevMode() + } + + const mount = () => { + if (element || !renderCompleted || !shouldMount()) return + + element = document.body.appendChild(document.createElement('div')) + element.classList.add('tsqd-parent-container') + devtools.mount(element) + } + + const unmount = () => { + if (!element) return + + devtools.unmount() + element.remove() + element = null + } + + afterNextRender({ + write: () => { + if (destroyRef.destroyed) return + + renderCompleted = true + mount() + destroyRef.onDestroy(unmount) + }, + }) + + afterRenderEffect({ + write: () => { + if (!renderCompleted) return + shouldMount() ? mount() : unmount() + }, + }) + + const registerOptionEffect = ( + option: T | Signal | undefined, + update: (value: T | undefined) => void, + ) => { + if (!isSignal(option)) return + afterRenderEffect({ + write: () => { + update(option()) + }, + }) + } + + registerOptionEffect(options.client, (value) => { + devtools.setClient(value ?? injectedClient!) + }) + registerOptionEffect(options.buttonPosition, (value) => { + devtools.setButtonPosition(value ?? 'bottom-right') + }) + registerOptionEffect(options.position, (value) => { + devtools.setPosition(value ?? 'bottom') + }) + registerOptionEffect(options.initialIsOpen, (value) => { + devtools.setInitialIsOpen(value ?? false) + }) + registerOptionEffect(options.errorTypes, (value) => { + devtools.setErrorTypes(value ?? []) + }) + registerOptionEffect(options.theme, (value) => { + devtools.setTheme(value) + }) + }), + ]), + ) diff --git a/packages/angular-query-experimental/test-setup.ts b/packages/angular-query-devtools/test-setup.ts similarity index 91% rename from packages/angular-query-experimental/test-setup.ts rename to packages/angular-query-devtools/test-setup.ts index cb8519a824c..eb69f3f05a9 100644 --- a/packages/angular-query-experimental/test-setup.ts +++ b/packages/angular-query-devtools/test-setup.ts @@ -1,4 +1,5 @@ import '@testing-library/jest-dom/vitest' +import '@angular/compiler' import { getTestBed } from '@angular/core/testing' import { BrowserTestingModule, diff --git a/packages/angular-query-devtools/tsconfig.json b/packages/angular-query-devtools/tsconfig.json new file mode 100644 index 00000000000..bec09d17d91 --- /dev/null +++ b/packages/angular-query-devtools/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist-ts", + "rootDir": ".", + "noFallthroughCasesInSwitch": true, + "useDefineForClassFields": false, + "target": "ES2022" + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictStandalone": true, + "strictTemplates": true + }, + "include": ["src", "scripts", "test-setup.ts", "*.config.*", "package.json"], + "references": [ + { "path": "../angular-query" }, + { "path": "../query-core" }, + { "path": "../query-devtools" } + ] +} diff --git a/packages/angular-query-devtools/tsconfig.prod.json b/packages/angular-query-devtools/tsconfig.prod.json new file mode 100644 index 00000000000..b470042ddc1 --- /dev/null +++ b/packages/angular-query-devtools/tsconfig.prod.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "incremental": false, + "composite": false, + "rootDir": "../../", + "customConditions": null + } +} diff --git a/packages/angular-query-devtools/tsconfig.spec.json b/packages/angular-query-devtools/tsconfig.spec.json new file mode 100644 index 00000000000..b15a2a37c7b --- /dev/null +++ b/packages/angular-query-devtools/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "types": ["vitest/globals", "node"], + "noEmit": false, + "emitDeclarationOnly": false, + "declaration": false, + "declarationMap": false, + "composite": false, + "target": "ES2022" + }, + "files": ["test-setup.ts"], + "include": ["src/**/*.test.ts", "src/**/*.test-d.ts"], + "references": [{ "path": "./tsconfig.prod.json" }] +} diff --git a/packages/angular-query-devtools/vite.config.ts b/packages/angular-query-devtools/vite.config.ts new file mode 100644 index 00000000000..cac0f34027f --- /dev/null +++ b/packages/angular-query-devtools/vite.config.ts @@ -0,0 +1,126 @@ +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import { defineConfig, mergeConfig } from 'vite' +import { externalizeDeps } from 'vite-plugin-externalize-deps' +import tsconfigPaths from 'vite-tsconfig-paths' +import dts from 'vite-plugin-dts' +import type { Options } from '@tanstack/vite-config' + +const packageDir = path.dirname(fileURLToPath(import.meta.url)) +const angularQueryEntry = path.join( + packageDir, + '../angular-query/dist/index.mjs', +) +const angularQueryInternalEntry = path.join( + packageDir, + '../angular-query/dist/internal.mjs', +) +const queryDevtoolsEntry = path.join( + packageDir, + '../query-devtools/src/index.ts', +) + +function ensureImportFileExtension({ + content, + extension, +}: { + content: string + extension: string +}) { + content = content.replace( + /(im|ex)port\s[\w{}/*\s,]+from\s['"](?:\.\.?\/)+?[^.'"]+(?=['"];?)/gm, + `$&.${extension}`, + ) + + content = content.replace( + /import\(['"](?:\.\.?\/)+?[^.'"]+(?=['"];?)/gm, + `$&.${extension}`, + ) + return content +} + +const config = defineConfig({ + resolve: { + conditions: ['@tanstack/custom-condition'], + ...(process.env.VITEST === 'true' + ? { + alias: { + '@tanstack/angular-query/internal': angularQueryInternalEntry, + '@tanstack/angular-query': angularQueryEntry, + '@tanstack/query-devtools': queryDevtoolsEntry, + }, + } + : {}), + }, +}) + +export const tanstackViteConfig = (options: Options) => { + const outDir = options.outDir ?? 'dist' + const cjs = options.cjs ?? true + + return defineConfig({ + plugins: [ + externalizeDeps({ include: options.externalDeps ?? [] }), + tsconfigPaths({ + projects: options.tsconfigPath ? [options.tsconfigPath] : undefined, + }), + dts({ + outDir, + entryRoot: options.srcDir, + include: options.srcDir, + exclude: options.exclude, + tsconfigPath: options.tsconfigPath, + compilerOptions: { + module: 99, // ESNext + declarationMap: false, + }, + beforeWriteFile: (filePath, content) => { + return { + filePath, + content: ensureImportFileExtension({ content, extension: 'js' }), + } + }, + afterDiagnostic: (diagnostics) => { + if (diagnostics.length > 0) { + console.error('Please fix the above type errors') + process.exit(1) + } + }, + }), + ], + build: { + outDir, + minify: false, + sourcemap: true, + lib: { + entry: options.entry, + formats: cjs ? ['es', 'cjs'] : ['es'], + fileName: () => '[name].mjs', + }, + rollupOptions: { + output: { + preserveModules: true, + preserveModulesRoot: 'src', + }, + }, + }, + }) +} + +export default mergeConfig( + config, + tanstackViteConfig({ + cjs: false, + entry: [ + './src/index.ts', + './src/stub.ts', + './src/production/index.ts', + './src/devtools-panel/index.ts', + './src/devtools-panel/stub.ts', + './src/devtools-panel/production/index.ts', + ], + exclude: ['src/__tests__'], + srcDir: './src', + tsconfigPath: 'tsconfig.prod.json', + }), +) diff --git a/packages/angular-query-devtools/vitest.config.ts b/packages/angular-query-devtools/vitest.config.ts new file mode 100644 index 00000000000..7f5ed075a45 --- /dev/null +++ b/packages/angular-query-devtools/vitest.config.ts @@ -0,0 +1,43 @@ +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import angular from '@analogjs/vite-plugin-angular' +import { defineConfig } from 'vitest/config' +import packageJson from './package.json' with { type: 'json' } + +const packageDir = path.dirname(fileURLToPath(import.meta.url)) +const angularQueryEntry = path.join( + packageDir, + '../angular-query/dist/index.mjs', +) +const angularQueryInternalEntry = path.join( + packageDir, + '../angular-query/dist/internal.mjs', +) + +export default defineConfig({ + esbuild: { + target: 'es2022', + }, + plugins: [angular({ tsconfig: './tsconfig.spec.json' })], + resolve: { + alias: { + '@tanstack/angular-query/internal': angularQueryInternalEntry, + '@tanstack/angular-query': angularQueryEntry, + '@tanstack/query-devtools': path.join( + packageDir, + '../query-devtools/src/index.ts', + ), + }, + }, + test: { + name: packageJson.name, + dir: './src', + watch: false, + environment: 'jsdom', + setupFiles: ['./test-setup.ts'], + coverage: { enabled: true, provider: 'istanbul', include: ['src/**/*'] }, + include: ['**/*.{test,spec}.{ts,mts,cts,tsx,js,mjs,cjs,jsx}'], + globals: true, + restoreMocks: true, + }, +}) diff --git a/packages/angular-query-experimental/CHANGELOG.md b/packages/angular-query-experimental/CHANGELOG.md deleted file mode 100644 index b2cebae74e3..00000000000 --- a/packages/angular-query-experimental/CHANGELOG.md +++ /dev/null @@ -1,499 +0,0 @@ -# @tanstack/angular-query-experimental - -## 5.103.2 - -### Patch Changes - -- Updated dependencies [[`8a28904`](https://github.com/TanStack/query/commit/8a28904aaccb6bc26398b751400a181c0f6d7f0e)]: - - @tanstack/query-core@5.103.2 - -## 5.103.1 - -### Patch Changes - -- Updated dependencies [[`8330b2f`](https://github.com/TanStack/query/commit/8330b2f2d431f226d7bb95eb727c637be9d4c6d8), [`3212966`](https://github.com/TanStack/query/commit/3212966a3681e02d14eb79e9cce0d3265b046877)]: - - @tanstack/query-core@5.103.1 - -## 5.103.0 - -### Patch Changes - -- Updated dependencies [[`e57f816`](https://github.com/TanStack/query/commit/e57f8163b18ab3abfe52ad69cdbdda4d31453393), [`fdae2ce`](https://github.com/TanStack/query/commit/fdae2ce4e5382af7326c7c38ce5d5a12751ada12), [`a1119e5`](https://github.com/TanStack/query/commit/a1119e5a3ffa52534de7390f17c7183d17658051), [`cbf77bf`](https://github.com/TanStack/query/commit/cbf77bf8e1a9ce09caef0cdd9a8ed10fef57edf0)]: - - @tanstack/query-core@5.103.0 - -## 5.102.8 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.102.8 - -## 5.102.7 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.102.7 - -## 5.102.6 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.102.6 - -## 5.102.5 - -### Patch Changes - -- Updated dependencies [[`578e5c2`](https://github.com/TanStack/query/commit/578e5c26e8ebd0d7351b4b8e2bafba695e672b8d)]: - - @tanstack/query-core@5.102.5 - -## 5.102.4 - -### Patch Changes - -- Updated dependencies [[`a05df6a`](https://github.com/TanStack/query/commit/a05df6aefb0e2489ec2c879ae16e2ee7cb3123ec)]: - - @tanstack/query-core@5.102.4 - -## 5.102.3 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.102.3 - -## 5.102.2 - -### Patch Changes - -- Updated dependencies [[`80fbf73`](https://github.com/TanStack/query/commit/80fbf73e77892d702c107e14a84c219a8ed825dc)]: - - @tanstack/query-core@5.102.2 - -## 5.102.1 - -### Patch Changes - -- Updated dependencies [[`134890d`](https://github.com/TanStack/query/commit/134890dbdc60e4fb0313e44b512d29284ca82f96)]: - - @tanstack/query-core@5.102.1 - -## 5.102.0 - -### Patch Changes - -- [#11224](https://github.com/TanStack/query/pull/11224) [`294d4e6`](https://github.com/TanStack/query/commit/294d4e62c4f7d674574a4903eef2a1bc3dd1413b) - Fix `queryOptions` and `infiniteQueryOptions` return types so exported inferred options can be emitted in declaration files without leaking internal data tag symbols. - -- [#8737](https://github.com/TanStack/query/pull/8737) [`2215bb0`](https://github.com/TanStack/query/commit/2215bb031139cdc8a84751b37a485c38ca9d2b6e) - fix: make mutation variables optional when `undefined extends TVariables` - -- [#11221](https://github.com/TanStack/query/pull/11221) [`1ef4208`](https://github.com/TanStack/query/commit/1ef42087c9a266c2137d2ef645cbcc662f60ac93) - Remove experimental render-time prefetching and the `promise` property from query results. - -- Updated dependencies [[`34f7cee`](https://github.com/TanStack/query/commit/34f7ceed09c10e4a3aa2df31a106ddf02ec4e787), [`b4368c4`](https://github.com/TanStack/query/commit/b4368c43792349f6c29d1fb41f7ee1ef3a8bdd2c), [`5bb089d`](https://github.com/TanStack/query/commit/5bb089d153d33933983b7ea80f8d69b51d423698), [`ba4650c`](https://github.com/TanStack/query/commit/ba4650c05e61e33c609e051b948c9f7d31ce70d1), [`294d4e6`](https://github.com/TanStack/query/commit/294d4e62c4f7d674574a4903eef2a1bc3dd1413b), [`1f631b3`](https://github.com/TanStack/query/commit/1f631b3604aab6567fb3f6c90646a5a304641546), [`01a02bf`](https://github.com/TanStack/query/commit/01a02bfad32f9efbc17796be31d6399f1197a655), [`18c1c1e`](https://github.com/TanStack/query/commit/18c1c1ef94883e781ad36d36f9ea4a043ce4260b), [`5448063`](https://github.com/TanStack/query/commit/5448063f828d2270dccd41ae375e1afde35e91f2), [`2215bb0`](https://github.com/TanStack/query/commit/2215bb031139cdc8a84751b37a485c38ca9d2b6e), [`1ef4208`](https://github.com/TanStack/query/commit/1ef42087c9a266c2137d2ef645cbcc662f60ac93), [`5981771`](https://github.com/TanStack/query/commit/5981771abec9330b344a2617543eb05ba7c99e24), [`4a9bef6`](https://github.com/TanStack/query/commit/4a9bef6cf19b1cd6b014032d696129f12a848185), [`bef4bc7`](https://github.com/TanStack/query/commit/bef4bc780ce7cca32b7e3dea85f77d92f82a62a2), [`9656dc4`](https://github.com/TanStack/query/commit/9656dc4e5fef5f8c502579b52459f9e8c72e787c), [`326aaf1`](https://github.com/TanStack/query/commit/326aaf1333e5d9cbc46569c53f218d31684162d2), [`3e83601`](https://github.com/TanStack/query/commit/3e836010032c2586e9f1c66a271fa9114a6401f9), [`c6fc17c`](https://github.com/TanStack/query/commit/c6fc17cfad6e452261c585fabfb8c210e60531ed)]: - - @tanstack/query-core@5.102.0 - -## 5.101.4 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.101.4 - -## 5.101.3 - -### Patch Changes - -- Updated dependencies [[`7e3c822`](https://github.com/TanStack/query/commit/7e3c822a10896f41a8f1031c16b85096277af677)]: - - @tanstack/query-core@5.101.3 - -## 5.101.2 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.101.2 - -## 5.101.1 - -### Patch Changes - -- Updated dependencies [[`9eff92e`](https://github.com/TanStack/query/commit/9eff92ed86e284ec0125b3a3539d028688235bd1)]: - - @tanstack/query-core@5.101.1 - -## 5.101.0 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.101.0 - -## 5.100.14 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.100.14 - -## 5.100.13 - -### Patch Changes - -- Updated dependencies [[`d423168`](https://github.com/TanStack/query/commit/d423168f6261a5cb3d353e53b27c8150cc271151)]: - - @tanstack/query-core@5.100.13 - -## 5.100.12 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.100.12 - -## 5.100.11 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.100.11 - -## 5.100.10 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.100.10 - -## 5.100.9 - -### Patch Changes - -- Add theme option support to Angular floating devtools. ([#10609](https://github.com/TanStack/query/pull/10609)) - -- Updated dependencies [[`fcee7bd`](https://github.com/TanStack/query/commit/fcee7bdc429385ae8ffa224fa8a7a9ec7b8ee380)]: - - @tanstack/query-core@5.100.9 - -## 5.100.8 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.100.8 - -## 5.100.7 - -### Patch Changes - -- docs(devtools): align logo, panel, and 'buttonPosition' union descriptions across docs and JSDoc ([#10617](https://github.com/TanStack/query/pull/10617)) - -- Updated dependencies []: - - @tanstack/query-core@5.100.7 - -## 5.100.6 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.100.6 - -## 5.100.5 - -### Patch Changes - -- Updated dependencies [[`a53ef97`](https://github.com/TanStack/query/commit/a53ef97f87decb8ea2431710f5199431d3c94c8d)]: - - @tanstack/query-core@5.100.5 - -## 5.100.4 - -### Patch Changes - -- fix(devtools): change onClose callback type from () => unknown to () => void ([#10118](https://github.com/TanStack/query/pull/10118)) - -- Updated dependencies []: - - @tanstack/query-core@5.100.4 - -## 5.100.3 - -### Patch Changes - -- Updated dependencies [[`f85d825`](https://github.com/TanStack/query/commit/f85d825e02efbbff02e2081528ed28f5e5382f7a)]: - - @tanstack/query-core@5.100.3 - -## 5.100.2 - -### Patch Changes - -- Updated dependencies [[`ea4497e`](https://github.com/TanStack/query/commit/ea4497e8aa00d8c1c3a36fb1e17563a889d6ab31), [`d6a7bf3`](https://github.com/TanStack/query/commit/d6a7bf3e3e024c1a77d0536813238cc8007a5fa7), [`645d5d1`](https://github.com/TanStack/query/commit/645d5d130f5e8017cb1bf1a37987f7b980aed705)]: - - @tanstack/query-core@5.100.2 - -## 5.100.1 - -### Patch Changes - -- Updated dependencies [[`1bb0d23`](https://github.com/TanStack/query/commit/1bb0d234280fd4ae1725c439088426a20593a8df)]: - - @tanstack/query-core@5.100.1 - -## 5.100.0 - -### Patch Changes - -- Updated dependencies [[`6540a41`](https://github.com/TanStack/query/commit/6540a4126b1c087d86d64525e78f32d9920dcd31)]: - - @tanstack/query-core@5.100.0 - -## 5.99.2 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.99.2 - -## 5.99.1 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.99.1 - -## 5.99.0 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.99.0 - -## 5.98.0 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.98.0 - -## 5.97.0 - -### Patch Changes - -- Updated dependencies [[`2bfb12c`](https://github.com/TanStack/query/commit/2bfb12cc44f1d8495106136e4ddacb817135f8f9)]: - - @tanstack/query-core@5.97.0 - -## 5.96.2 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.96.2 - -## 5.96.1 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.96.1 - -## 5.96.0 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.96.0 - -## 5.95.2 - -### Patch Changes - -- Updated dependencies [[`cd5a35b`](https://github.com/TanStack/query/commit/cd5a35b328837781aa4f9305bb2bd7877ca934e9)]: - - @tanstack/query-core@5.95.2 - -## 5.95.1 - -### Patch Changes - -- Updated dependencies [[`1f1775c`](https://github.com/TanStack/query/commit/1f1775ca92f2b6c035682947ff3b3424804ff31a)]: - - @tanstack/query-core@5.95.1 - -## 5.95.0 - -### Patch Changes - -- Updated dependencies []: - - @tanstack/query-core@5.95.0 - -## 5.94.5 - -### Patch Changes - -- fix(\*): resolve issue about excluded build directory ([#10312](https://github.com/TanStack/query/pull/10312)) - -- Updated dependencies [[`4b6536d`](https://github.com/TanStack/query/commit/4b6536dfce99036f4e37f52943c6fed3ad0e0a18)]: - - @tanstack/query-core@5.94.5 - -## 5.94.4 - -### Patch Changes - -- chore: fixed version ([#10064](https://github.com/TanStack/query/pull/10064)) - -- Updated dependencies [[`4c75210`](https://github.com/TanStack/query/commit/4c75210ce8235fe3d39b67e1029eff11278927cc)]: - - @tanstack/query-core@5.94.4 - -## 5.90.28 - -### Patch Changes - -- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287)) - -- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]: - - @tanstack/query-core@5.91.2 - -## 5.90.27 - -### Patch Changes - -- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]: - - @tanstack/query-core@5.91.1 - -## 5.90.26 - -### Patch Changes - -- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]: - - @tanstack/query-core@5.91.0 - -## 5.90.25 - -## 5.90.24 - -### Patch Changes - -- Updated dependencies [[`e7258c5`](https://github.com/TanStack/query/commit/e7258c5cb30cafa456cdb4e6bc75b43bf619954d)]: - - @tanstack/query-core@5.90.20 - -## 5.90.23 - -### Patch Changes - -- Updated dependencies [[`53fc74e`](https://github.com/TanStack/query/commit/53fc74ebb16730bd3317f039a69c6821386bae93)]: - - @tanstack/query-core@5.90.19 - -## 5.90.22 - -### Patch Changes - -- Updated dependencies [[`dea1614`](https://github.com/TanStack/query/commit/dea1614aaad5c572cf43cea54b64ac09dc4d5b41)]: - - @tanstack/query-core@5.90.18 - -## 5.90.21 - -### Patch Changes - -- Updated dependencies [[`269351b`](https://github.com/TanStack/query/commit/269351b8ce4b4846da3d320ac5b850ee6aada0d6)]: - - @tanstack/query-core@5.90.17 - -## 5.90.20 - -### Patch Changes - -- Updated dependencies [[`7f47906`](https://github.com/TanStack/query/commit/7f47906eaccc3f3aa5ce24b77a83bd7a620a237b)]: - - @tanstack/query-core@5.90.16 - -## 5.90.19 - -### Patch Changes - -- Updated dependencies [[`fccef79`](https://github.com/TanStack/query/commit/fccef797d57d4a9566517bba87c8377f363920f2)]: - - @tanstack/query-core@5.90.15 - -## 5.90.18 - -### Patch Changes - -- Updated dependencies [[`d576092`](https://github.com/TanStack/query/commit/d576092e2ece4ca3936add3eb0da5234c1d82ed4)]: - - @tanstack/query-core@5.90.14 - -## 5.90.17 - -### Patch Changes - -- Updated dependencies [[`4a0a78a`](https://github.com/TanStack/query/commit/4a0a78afbc2432f8cb6828035965853fa98c86a0)]: - - @tanstack/query-core@5.90.13 - -## 5.90.16 - -### Patch Changes - -- Updated dependencies [[`72d8ac5`](https://github.com/TanStack/query/commit/72d8ac5c592004b8f9c3ee086fcb9c3cd615ca05)]: - - @tanstack/query-core@5.90.12 - -## 5.90.15 - -### Patch Changes - -- Updated dependencies [[`c01b150`](https://github.com/TanStack/query/commit/c01b150e3673e11d6533768529a5e6fe3ebee68c)]: - - @tanstack/query-core@5.90.11 - -## 5.90.14 - -## 5.90.13 - -## 5.90.12 - -### Patch Changes - -- Updated dependencies [[`8e2e174`](https://github.com/TanStack/query/commit/8e2e174e9fd2e7b94cd232041e49c9d014d74e26), [`eb559a6`](https://github.com/TanStack/query/commit/eb559a66dc0d77dd46435f624fa64fc068bef9ae)]: - - @tanstack/query-core@5.90.10 - -## 5.90.11 - -### Patch Changes - -- Updated dependencies [[`08b211f`](https://github.com/TanStack/query/commit/08b211f8aa475e05d2f13a36517fc556861ef962)]: - - @tanstack/query-core@5.90.9 - -## 5.90.10 - -### Patch Changes - -- Updated dependencies [[`c0ec9fe`](https://github.com/TanStack/query/commit/c0ec9fe0d1426fe3f233adda3ebf23989ffaa110)]: - - @tanstack/query-core@5.90.8 - -## 5.90.9 - -### Patch Changes - -- Updated dependencies [[`b4cd121`](https://github.com/TanStack/query/commit/b4cd121a39d07cefaa3a3411136d342cc54ce8fb)]: - - @tanstack/query-core@5.90.7 - -## 5.90.8 - -### Patch Changes - -- Updated dependencies [[`1638c02`](https://github.com/TanStack/query/commit/1638c028df55648995d04431179904371a189772)]: - - @tanstack/query-core@5.90.6 - -## 5.90.7 - -### Patch Changes - -- Make `injectIsMutating` signal read-only to prevent external modifications to the internal state ([#9801](https://github.com/TanStack/query/pull/9801)) - -## 5.90.6 - -### Patch Changes - -- Rename `DeveloperToolsFeature` to `DevtoolsFeature` for consistency with internal naming conventions and ecosystem ([#9794](https://github.com/TanStack/query/pull/9794)) - -## 5.90.5 - -### Patch Changes - -- Updated dependencies [[`e42ddfe`](https://github.com/TanStack/query/commit/e42ddfe919f34f847ca101aeef162c69845f9a1e)]: - - @tanstack/query-core@5.90.5 - -## 5.90.4 - -### Patch Changes - -- Updated dependencies [[`20ef922`](https://github.com/TanStack/query/commit/20ef922a0a7c3aee00150bf69123c338b0922922)]: - - @tanstack/query-core@5.90.4 - -## 5.90.3 - -### Patch Changes - -- Updated dependencies [[`4e1c433`](https://github.com/TanStack/query/commit/4e1c4338a72f7384600bbda99e44bc1891695df4)]: - - @tanstack/query-core@5.90.3 diff --git a/packages/angular-query-experimental/package.json b/packages/angular-query-experimental/package.json deleted file mode 100644 index 209a5a64e93..00000000000 --- a/packages/angular-query-experimental/package.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "name": "@tanstack/angular-query-experimental", - "version": "5.103.2", - "description": "Signals for managing, caching and syncing asynchronous and remote data in Angular", - "author": "Arnoud de Vries", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/TanStack/query.git", - "directory": "packages/angular-query-experimental" - }, - "homepage": "https://tanstack.com/query", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "keywords": [ - "angular query", - "angular", - "cache", - "performance", - "reactive", - "rxjs", - "signals", - "state management", - "state", - "tanstack" - ], - "scripts": { - "clean": "premove ./dist ./coverage ./dist-ts ./.cache/test-types", - "compile": "tsc --project tsconfig.json", - "test:eslint": "eslint --concurrency=auto ./src", - "test:types": "npm-run-all --serial test:types:*", - "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts56 --tsBuildInfoFile .cache/test-types/ts56.tsbuildinfo", - "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts57 --tsBuildInfoFile .cache/test-types/ts57.tsbuildinfo", - "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts58 --tsBuildInfoFile .cache/test-types/ts58.tsbuildinfo", - "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts59 --tsBuildInfoFile .cache/test-types/ts59.tsbuildinfo", - "test:types:tscurrent": "tsc --project tsconfig.json --outDir .cache/test-types/tscurrent --tsBuildInfoFile .cache/test-types/tscurrent.tsbuildinfo", - "test:types:ts70": "node ../../node_modules/typescript70/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts70 --tsBuildInfoFile .cache/test-types/ts70.tsbuildinfo", - "test:lib": "vitest", - "test:lib:dev": "pnpm run test:lib --watch", - "test:build": "pnpm pack && publint ./dist/*.tgz --strict && attw ./dist/*.tgz; premove ./dist/*.tgz", - "build": "vite build", - "prepack": "node scripts/prepack.js" - }, - "type": "module", - "types": "dist/index.d.ts", - "module": "dist/index.mjs", - "exports": { - ".": { - "@tanstack/custom-condition": "./src/index.ts", - "types": "./dist/index.d.ts", - "default": "./dist/index.mjs" - }, - "./package.json": "./package.json", - "./inject-queries-experimental": { - "types": "./dist/inject-queries-experimental/index.d.ts", - "default": "./dist/inject-queries-experimental/index.mjs" - }, - "./devtools": { - "types": "./dist/devtools/index.d.ts", - "development": "./dist/devtools/index.mjs", - "default": "./dist/devtools/stub.mjs" - }, - "./devtools/production": { - "types": "./dist/devtools/production/index.d.ts", - "default": "./dist/devtools/index.mjs" - }, - "./devtools-panel": { - "types": "./dist/devtools-panel/index.d.ts", - "development": "./dist/devtools-panel/index.mjs", - "default": "./dist/devtools-panel/stub.mjs" - }, - "./devtools-panel/production": { - "types": "./dist/devtools-panel/production/index.d.ts", - "default": "./dist/devtools-panel/index.mjs" - } - }, - "sideEffects": false, - "files": [ - "**/*.d.ts", - "**/*.mjs", - "**/*.mjs.map" - ], - "dependencies": { - "@tanstack/query-core": "workspace:*" - }, - "devDependencies": { - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@tanstack/query-test-utils": "workspace:*", - "@testing-library/angular": "^18.0.0", - "npm-run-all2": "^5.0.0", - "rxjs": "^7.8.2", - "vite-plugin-dts": "4.2.3", - "vite-plugin-externalize-deps": "^0.9.0", - "vite-tsconfig-paths": "^5.1.4" - }, - "optionalDependencies": { - "@tanstack/query-devtools": "workspace:*" - }, - "peerDependencies": { - "@angular/common": ">=16.0.0", - "@angular/core": ">=16.0.0" - }, - "publishConfig": { - "directory": "dist", - "linkDirectory": false - } -} diff --git a/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.ts b/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.ts deleted file mode 100644 index 6e880ea494c..00000000000 --- a/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { TestBed } from '@angular/core/testing' -import { afterEach, beforeEach, describe, expectTypeOf, it, vi } from 'vitest' -import { provideZonelessChangeDetection } from '@angular/core' -import { queryKey, sleep } from '@tanstack/query-test-utils' -import { - QueryClient, - injectInfiniteQuery, - provideTanStackQuery, - skipToken, -} from '..' -import type { InfiniteData } from '@tanstack/query-core' - -describe('injectInfiniteQuery', () => { - let queryClient: QueryClient - - beforeEach(() => { - queryClient = new QueryClient() - vi.useFakeTimers() - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), - ], - }) - }) - - afterEach(() => { - vi.useRealTimers() - }) - - it('should narrow type after isSuccess', () => { - const key = queryKey() - const query = TestBed.runInInjectionContext(() => { - return injectInfiniteQuery(() => ({ - queryKey: key, - queryFn: ({ pageParam }) => - sleep(0).then(() => 'data on page ' + pageParam), - initialPageParam: 0, - getNextPageParam: () => 12, - })) - }) - - if (query.isSuccess()) { - const data = query.data() - expectTypeOf(data).toEqualTypeOf>() - } - }) - - it('should work when queryFn is skipToken', () => { - const key = queryKey() - const query = TestBed.runInInjectionContext(() => { - return injectInfiniteQuery(() => ({ - queryKey: key, - queryFn: skipToken, - initialPageParam: 0, - getNextPageParam: () => 1, - })) - }) - - // TPageParam falls back to `unknown` here (unlike `infiniteQueryOptions`, which infers - // `number` for the same options) because there's no skipToken-specific overload to carry it. - expectTypeOf(query.data()).toEqualTypeOf< - InfiniteData | undefined - >() - }) -}) diff --git a/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts b/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts deleted file mode 100644 index 7f14ec24459..00000000000 --- a/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { TestBed } from '@angular/core/testing' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { - Component, - Injector, - provideZonelessChangeDetection, - signal, -} from '@angular/core' -import { render } from '@testing-library/angular' -import { queryKey, sleep } from '@tanstack/query-test-utils' -import { - QueryClient, - injectInfiniteQuery, - provideTanStackQuery, - skipToken, -} from '..' - -describe('injectInfiniteQuery', () => { - let queryClient: QueryClient - - beforeEach(() => { - queryClient = new QueryClient() - vi.useFakeTimers() - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), - ], - }) - }) - - afterEach(() => { - vi.useRealTimers() - }) - - it('should properly execute infinite query', async () => { - const key = queryKey() - - @Component({ - template: ` -
status: {{ query.status() }}
-
pages: {{ query.data()?.pages?.join(', ') ?? 'none' }}
- `, - }) - class Page { - readonly query = injectInfiniteQuery(() => ({ - queryKey: key, - queryFn: ({ pageParam }) => - sleep(10).then(() => 'data on page ' + pageParam), - initialPageParam: 0, - getNextPageParam: () => 12, - })) - } - - const rendered = await render(Page) - - expect(rendered.getByText('status: pending')).toBeInTheDocument() - expect(rendered.getByText('pages: none')).toBeInTheDocument() - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - expect(rendered.getByText('status: success')).toBeInTheDocument() - expect(rendered.getByText('pages: data on page 0')).toBeInTheDocument() - - rendered.fixture.componentInstance.query.fetchNextPage() - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - expect(rendered.getByText('status: success')).toBeInTheDocument() - expect( - rendered.getByText('pages: data on page 0, data on page 12'), - ).toBeInTheDocument() - }) - - it('should reject and update signal', async () => { - const key = queryKey() - - @Component({ - template: ` -
status: {{ query.status() }}
-
pages: {{ query.data()?.pages?.join(', ') ?? 'none' }}
-
error: {{ query.error()?.message ?? 'none' }}
-
isError: {{ query.isError() }}
-
failureCount: {{ query.failureCount() }}
- `, - }) - class Page { - readonly query = injectInfiniteQuery(() => ({ - retry: false, - queryKey: key, - queryFn: () => - sleep(10).then(() => Promise.reject(new Error('Some error'))), - initialPageParam: 0, - getNextPageParam: () => 12, - })) - } - - const rendered = await render(Page) - - expect(rendered.getByText('status: pending')).toBeInTheDocument() - expect(rendered.getByText('pages: none')).toBeInTheDocument() - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - - expect(rendered.getByText('status: error')).toBeInTheDocument() - expect(rendered.getByText('pages: none')).toBeInTheDocument() - expect(rendered.getByText('error: Some error')).toBeInTheDocument() - expect(rendered.getByText('isError: true')).toBeInTheDocument() - expect(rendered.getByText('failureCount: 1')).toBeInTheDocument() - }) - - it('should keep initialData visible alongside the error when a refetch fails', async () => { - const key = queryKey() - - @Component({ - template: ` -
pages: {{ query.data().pages.join(', ') }}
-
isError: {{ query.isError() }}
- `, - }) - class Page { - readonly query = injectInfiniteQuery(() => ({ - queryKey: key, - queryFn: () => - sleep(10).then(() => Promise.reject(new Error('Some error'))), - initialData: { pages: [1], pageParams: [1] }, - getNextPageParam: (lastPage: number) => lastPage + 1, - initialPageParam: 0, - retry: false, - })) - } - - const rendered = await render(Page) - - expect(rendered.getByText('pages: 1')).toBeInTheDocument() - expect(rendered.getByText('isError: false')).toBeInTheDocument() - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - expect(rendered.getByText('pages: 1')).toBeInTheDocument() - expect(rendered.getByText('isError: true')).toBeInTheDocument() - }) - - describe('skipToken', () => { - it('should not fetch when queryFn is skipToken, and fetch once it is replaced', async () => { - const key = queryKey() - const queryFn = vi.fn(({ pageParam }: { pageParam: number }) => - sleep(10).then(() => `comments for 1 page ${pageParam}`), - ) - - @Component({ - template: ` -
status: {{ query.status() }}
-
isFetching: {{ query.isFetching() }}
-
pages: {{ query.data()?.pages?.join(', ') ?? 'none' }}
- `, - }) - class Page { - postId = signal(undefined) - - readonly query = injectInfiniteQuery(() => ({ - queryKey: key, - queryFn: this.postId() != null ? queryFn : skipToken, - initialPageParam: 0, - getNextPageParam: () => 12, - })) - } - - const rendered = await render(Page) - - expect(rendered.getByText('status: pending')).toBeInTheDocument() - expect(rendered.getByText('isFetching: false')).toBeInTheDocument() - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - expect(queryFn).not.toHaveBeenCalled() - expect(rendered.getByText('status: pending')).toBeInTheDocument() - expect(rendered.getByText('isFetching: false')).toBeInTheDocument() - - rendered.fixture.componentInstance.postId.set('1') - rendered.fixture.detectChanges() - expect(rendered.getByText('isFetching: true')).toBeInTheDocument() - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - expect(queryFn).toHaveBeenCalledTimes(1) - expect(rendered.getByText('status: success')).toBeInTheDocument() - expect( - rendered.getByText('pages: comments for 1 page 0'), - ).toBeInTheDocument() - }) - }) - - describe('injection context', () => { - it('should throw NG0203 with descriptive error outside injection context', () => { - const key = queryKey() - expect(() => { - injectInfiniteQuery(() => ({ - queryKey: key, - queryFn: ({ pageParam }) => - sleep(0).then(() => 'data on page ' + pageParam), - initialPageParam: 0, - getNextPageParam: () => 12, - })) - }).toThrow(/NG0203(.*?)injectInfiniteQuery/) - }) - - it('should be usable outside injection context when passing an injector', () => { - const key = queryKey() - const query = injectInfiniteQuery( - () => ({ - queryKey: key, - queryFn: ({ pageParam }) => - sleep(0).then(() => 'data on page ' + pageParam), - initialPageParam: 0, - getNextPageParam: () => 12, - }), - { - injector: TestBed.inject(Injector), - }, - ) - - expect(query.status()).toBe('pending') - }) - }) -}) diff --git a/packages/angular-query-experimental/src/__tests__/inject-is-restoring.test.ts b/packages/angular-query-experimental/src/__tests__/inject-is-restoring.test.ts deleted file mode 100644 index 72ca01f9d69..00000000000 --- a/packages/angular-query-experimental/src/__tests__/inject-is-restoring.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { TestBed } from '@angular/core/testing' -import { beforeEach, describe, expect, it } from 'vitest' -import { Injector, provideZonelessChangeDetection, signal } from '@angular/core' -import { - QueryClient, - injectIsRestoring, - provideIsRestoring, - provideTanStackQuery, -} from '..' - -describe('injectIsRestoring', () => { - let queryClient: QueryClient - - beforeEach(() => { - queryClient = new QueryClient() - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), - ], - }) - }) - - it('should return false by default when provideIsRestoring is not used', () => { - const isRestoring = TestBed.runInInjectionContext(() => { - return injectIsRestoring() - }) - - expect(isRestoring()).toBe(false) - }) - - it('should return the provided signal value when provideIsRestoring is used', () => { - const restoringSignal = signal(true) - - TestBed.configureTestingModule({ - providers: [provideIsRestoring(restoringSignal.asReadonly())], - }) - - const isRestoring = TestBed.runInInjectionContext(() => { - return injectIsRestoring() - }) - - expect(isRestoring()).toBe(true) - }) - - it('should reactively reflect changes to the provided signal', () => { - const restoringSignal = signal(true) - - TestBed.configureTestingModule({ - providers: [provideIsRestoring(restoringSignal.asReadonly())], - }) - - const isRestoring = TestBed.runInInjectionContext(() => { - return injectIsRestoring() - }) - - expect(isRestoring()).toBe(true) - - restoringSignal.set(false) - expect(isRestoring()).toBe(false) - - restoringSignal.set(true) - expect(isRestoring()).toBe(true) - }) - - it('should be usable outside injection context when passing an injector', () => { - const isRestoring = injectIsRestoring({ - injector: TestBed.inject(Injector), - }) - - expect(isRestoring()).toBe(false) - }) - - it('should return the provided signal value when using injector option', () => { - const restoringSignal = signal(true) - - TestBed.configureTestingModule({ - providers: [provideIsRestoring(restoringSignal.asReadonly())], - }) - - const isRestoring = injectIsRestoring({ - injector: TestBed.inject(Injector), - }) - - expect(isRestoring()).toBe(true) - }) - - it('should throw NG0203 with descriptive error outside injection context', () => { - expect(() => { - injectIsRestoring() - }).toThrow(/NG0203(.*?)injectIsRestoring/) - }) -}) diff --git a/packages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts b/packages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts deleted file mode 100644 index b133575746c..00000000000 --- a/packages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts +++ /dev/null @@ -1,196 +0,0 @@ -import { describe, expectTypeOf, it } from 'vitest' -import { queryKey } from '@tanstack/query-test-utils' -import { skipToken } from '..' -import { injectQueries } from '../inject-queries' -import { queryOptions } from '../query-options' -import type { CreateQueryOptions, CreateQueryResult, OmitKeyof } from '..' -import type { Signal } from '@angular/core' - -describe('injectQueries', () => { - describe('config object overload', () => { - it('TData should always be defined when initialData is provided as an object', () => { - const key1 = queryKey() - const key2 = queryKey() - const key3 = queryKey() - - const query1 = { - queryKey: key1, - queryFn: () => { - return { - wow: true, - } - }, - initialData: { - wow: false, - }, - } - - const query2 = { - queryKey: key2, - queryFn: () => 'Query Data', - initialData: 'initial data', - } - - const query3 = { - queryKey: key3, - queryFn: () => 'Query Data', - } - - const queryResults = injectQueries(() => ({ - queries: [query1, query2, query3], - })) - - const query1Data = queryResults()[0].data() - const query2Data = queryResults()[1].data() - const query3Data = queryResults()[2].data() - - expectTypeOf(query1Data).toEqualTypeOf<{ wow: boolean }>() - expectTypeOf(query2Data).toEqualTypeOf() - expectTypeOf(query3Data).toEqualTypeOf() - }) - - it('TData should be defined when passed through queryOptions', () => { - const key = queryKey() - const options = queryOptions({ - queryKey: key, - queryFn: () => { - return { - wow: true, - } - }, - initialData: { - wow: true, - }, - }) - const queryResults = injectQueries(() => ({ queries: [options] })) - - const data = queryResults()[0].data() - - expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>() - }) - - it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into injectQuery', () => { - const key1 = queryKey() - const key2 = queryKey() - - const query1 = queryOptions({ - queryKey: key1, - queryFn: () => Promise.resolve(1), - select: (data) => data > 1, - }) - - const query2 = { - queryKey: key2, - queryFn: () => Promise.resolve(1), - select: (data: number) => data > 1, - } - - const queryResults = injectQueries(() => ({ queries: [query1, query2] })) - const query1Data = queryResults()[0].data() - const query2Data = queryResults()[1].data() - - expectTypeOf(query1Data).toEqualTypeOf() - expectTypeOf(query2Data).toEqualTypeOf() - }) - - it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { - const key = queryKey() - const queryResults = injectQueries(() => ({ - queries: [ - { - queryKey: key, - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => undefined as { wow: boolean } | undefined, - }, - ], - })) - - const data = queryResults()[0].data() - - expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>() - }) - - describe('custom injectable', () => { - it('should allow custom hooks using UseQueryOptions', () => { - type Data = string - const key = queryKey() - - const injectCustomQueries = ( - options?: OmitKeyof, 'queryKey' | 'queryFn'>, - ) => { - return injectQueries(() => ({ - queries: [ - { - ...options, - queryKey: key, - queryFn: () => Promise.resolve('data'), - }, - ], - })) - } - - const queryResults = injectCustomQueries() - const data = queryResults()[0].data() - - expectTypeOf(data).toEqualTypeOf() - }) - }) - - it('TData should have correct type when conditional skipToken is passed', () => { - const key = queryKey() - const queryResults = injectQueries(() => ({ - queries: [ - { - queryKey: key, - queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), - }, - ], - })) - - const firstResult = queryResults()[0] - - expectTypeOf(firstResult).toEqualTypeOf< - CreateQueryResult - >() - expectTypeOf(firstResult.data()).toEqualTypeOf() - }) - - it('should return correct data for dynamic queries with mixed result types', () => { - const key1 = queryKey() - const key2 = queryKey() - - const Queries1 = { - get: () => - queryOptions({ - queryKey: key1, - queryFn: () => Promise.resolve(1), - }), - } - const Queries2 = { - get: () => - queryOptions({ - queryKey: key2, - queryFn: () => Promise.resolve(true), - }), - } - - const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() })) - const result = injectQueries(() => ({ - queries: [...queries1List, { ...Queries2.get() }], - })) - - expectTypeOf(result).branded.toEqualTypeOf< - Signal< - [ - ...Array>, - CreateQueryResult, - ] - > - >() - }) - }) -}) diff --git a/packages/angular-query-experimental/src/__tests__/inject-queries.test.ts b/packages/angular-query-experimental/src/__tests__/inject-queries.test.ts deleted file mode 100644 index 523bda69f06..00000000000 --- a/packages/angular-query-experimental/src/__tests__/inject-queries.test.ts +++ /dev/null @@ -1,240 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { - Component, - effect, - provideZonelessChangeDetection, - signal, -} from '@angular/core' -import { TestBed } from '@angular/core/testing' -import { render } from '@testing-library/angular' -import { queryKey, sleep } from '@tanstack/query-test-utils' -import { QueryClient, provideIsRestoring, provideTanStackQuery } from '..' -import { injectQueries } from '../inject-queries' - -describe('injectQueries', () => { - let queryClient: QueryClient - - beforeEach(() => { - vi.useFakeTimers() - queryClient = new QueryClient() - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), - ], - }) - }) - - afterEach(() => { - vi.useRealTimers() - }) - - it('should return the correct states', async () => { - const key1 = queryKey() - const key2 = queryKey() - const results: Array>> = [] - - @Component({ - template: ` -
-
- data1: {{ result()[0].data() ?? 'null' }}, data2: - {{ result()[1].data() ?? 'null' }} -
-
- `, - }) - class Page { - readonly result = injectQueries(() => ({ - queries: [ - { - queryKey: key1, - queryFn: () => sleep(10).then(() => 1), - }, - { - queryKey: key2, - queryFn: () => sleep(100).then(() => 2), - }, - ], - })) - - constructor() { - effect(() => { - const snapshot = this.result().map((q) => ({ data: q.data() })) - results.push(snapshot) - }) - } - } - - const rendered = await render(Page) - - await vi.advanceTimersByTimeAsync(101) - rendered.fixture.detectChanges() - - expect(rendered.getByText('data1: 1, data2: 2')).toBeInTheDocument() - - expect(results.length).toBe(3) - expect(results[0]).toMatchObject([{ data: undefined }, { data: undefined }]) - expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }]) - expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }]) - }) - - it('should return the combined result when combine is provided', async () => { - const key1 = queryKey() - const key2 = queryKey() - const results: Array> = [] - - @Component({ - template: ` -
data: {{ combined().data.join(',') }}
-
isPending: {{ combined().isPending }}
- `, - }) - class Page { - readonly combined = injectQueries(() => ({ - queries: [ - { - queryKey: key1, - queryFn: () => sleep(10).then(() => 1), - }, - { - queryKey: key2, - queryFn: () => sleep(10).then(() => 2), - }, - ], - combine: (queries) => ({ - data: queries.map((q) => q.data), - isPending: queries.some((q) => q.isPending), - }), - })) - - constructor() { - effect(() => { - results.push({ ...this.combined() }) - }) - } - } - - const rendered = await render(Page) - - expect(rendered.getByText('data: ,')).toBeInTheDocument() - expect(rendered.getByText('isPending: true')).toBeInTheDocument() - expect(results[0]).toMatchObject({ - data: [undefined, undefined], - isPending: true, - }) - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - - expect(rendered.getByText('data: 1,2')).toBeInTheDocument() - expect(rendered.getByText('isPending: false')).toBeInTheDocument() - expect(results[results.length - 1]).toMatchObject({ - data: [1, 2], - isPending: false, - }) - expect(results.length).toBeGreaterThanOrEqual(2) - }) - - it('should reflect error state when one of the queries rejects', async () => { - const key1 = queryKey() - const key2 = queryKey() - - @Component({ - template: ` -
- status1: {{ result()[0].status() }}, error1: - {{ result()[0].error()?.message ?? 'none' }} -
-
- status2: {{ result()[1].status() }}, data2: - {{ result()[1].data() ?? 'none' }} -
- `, - }) - class Page { - readonly result = injectQueries(() => ({ - queries: [ - { - queryKey: key1, - queryFn: () => - sleep(10).then(() => Promise.reject(new Error('Some error'))), - retry: false, - }, - { - queryKey: key2, - queryFn: () => sleep(10).then(() => 2), - }, - ], - })) - } - - const rendered = await render(Page) - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - - expect( - rendered.getByText('status1: error, error1: Some error'), - ).toBeInTheDocument() - expect(rendered.getByText('status2: success, data2: 2')).toBeInTheDocument() - }) - - describe('isRestoring', () => { - it('should not fetch for the duration of the restoring period when isRestoring is true', async () => { - const key1 = queryKey() - const key2 = queryKey() - const queryFn1 = vi.fn().mockImplementation(() => sleep(10).then(() => 1)) - const queryFn2 = vi.fn().mockImplementation(() => sleep(10).then(() => 2)) - - TestBed.configureTestingModule({ - providers: [provideIsRestoring(signal(true).asReadonly())], - }) - - @Component({ - template: ` -
- status1: {{ queries()[0].status() }}, fetchStatus1: - {{ queries()[0].fetchStatus() }} -
-
- status2: {{ queries()[1].status() }}, fetchStatus2: - {{ queries()[1].fetchStatus() }} -
- `, - }) - class Page { - readonly queries = injectQueries(() => ({ - queries: [ - { queryKey: key1, queryFn: queryFn1 }, - { queryKey: key2, queryFn: queryFn2 }, - ], - })) - } - - const rendered = await render(Page) - - await vi.advanceTimersByTimeAsync(0) - rendered.fixture.detectChanges() - expect( - rendered.getByText('status1: pending, fetchStatus1: idle'), - ).toBeInTheDocument() - expect( - rendered.getByText('status2: pending, fetchStatus2: idle'), - ).toBeInTheDocument() - expect(queryFn1).toHaveBeenCalledTimes(0) - expect(queryFn2).toHaveBeenCalledTimes(0) - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - expect( - rendered.getByText('status1: pending, fetchStatus1: idle'), - ).toBeInTheDocument() - expect( - rendered.getByText('status2: pending, fetchStatus2: idle'), - ).toBeInTheDocument() - expect(queryFn1).toHaveBeenCalledTimes(0) - expect(queryFn2).toHaveBeenCalledTimes(0) - }) - }) -}) diff --git a/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts b/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts deleted file mode 100644 index 022e86ae87d..00000000000 --- a/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts +++ /dev/null @@ -1,357 +0,0 @@ -import { describe, expectTypeOf, it } from 'vitest' -import { queryKey, sleep } from '@tanstack/query-test-utils' -import { injectQuery, queryOptions } from '..' -import type { Signal } from '@angular/core' -import type { CreateQueryOptions, OmitKeyof, QueryFunction } from '..' - -describe('injectQuery', () => { - it('should return the correct types', () => { - const key = queryKey() - // unspecified query function should default to unknown - const noQueryFn = injectQuery(() => ({ - queryKey: key, - })) - expectTypeOf(noQueryFn.data()).toEqualTypeOf() - expectTypeOf(noQueryFn.error()).toEqualTypeOf() - - // it should infer the result type from the query function - const fromQueryFn = injectQuery(() => ({ - queryKey: key, - queryFn: () => 'test', - })) - expectTypeOf(fromQueryFn.data()).toEqualTypeOf() - expectTypeOf(fromQueryFn.error()).toEqualTypeOf() - - // it should be possible to specify the result type - const withResult = injectQuery(() => ({ - queryKey: key, - queryFn: () => 'test', - })) - expectTypeOf(withResult.data()).toEqualTypeOf() - expectTypeOf(withResult.error()).toEqualTypeOf() - - // it should be possible to specify the error type - type CustomErrorType = { message: string } - const withError = injectQuery(() => ({ - queryKey: key, - queryFn: () => 'test', - })) - expectTypeOf(withError.data()).toEqualTypeOf() - expectTypeOf(withError.error()).toEqualTypeOf() - - // it should infer the result type from the configuration - const withResultInfer = injectQuery(() => ({ - queryKey: key, - queryFn: () => true, - })) - expectTypeOf(withResultInfer.data()).toEqualTypeOf() - expectTypeOf(withResultInfer.error()).toEqualTypeOf() - - // it should be possible to specify a union type as result type - const unionTypeSync = injectQuery(() => ({ - queryKey: key, - queryFn: () => (Math.random() > 0.5 ? ('a' as const) : ('b' as const)), - })) - expectTypeOf(unionTypeSync.data()).toEqualTypeOf<'a' | 'b' | undefined>() - const unionTypeAsync = injectQuery<'a' | 'b'>(() => ({ - queryKey: key, - queryFn: () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'), - })) - expectTypeOf(unionTypeAsync.data()).toEqualTypeOf<'a' | 'b' | undefined>() - - // it should error when the query function result does not match with the specified type - // @ts-expect-error - injectQuery(() => ({ queryKey: key, queryFn: () => 'test' })) - - // it should infer the result type from a generic query function - /** - * - */ - function queryFn(): Promise { - return Promise.resolve({} as T) - } - - const fromGenericQueryFn = injectQuery(() => ({ - queryKey: key, - queryFn: () => queryFn(), - })) - expectTypeOf(fromGenericQueryFn.data()).toEqualTypeOf() - expectTypeOf(fromGenericQueryFn.error()).toEqualTypeOf() - - type MyData = number - type MyQueryKey = readonly ['my-data', number] - - const getMyDataArrayKey: QueryFunction = ({ - queryKey: [, n], - }) => { - return n + 42 - } - - const fromMyDataArrayKeyQueryFn = injectQuery(() => ({ - queryKey: ['my-data', 100] as const, - queryFn: getMyDataArrayKey, - })) - expectTypeOf(fromMyDataArrayKeyQueryFn.data()).toEqualTypeOf< - number | undefined - >() - - // it should handle query-functions that return Promise - const fromPromiseAnyQueryFn = injectQuery(() => ({ - queryKey: key, - queryFn: () => fetch('return Promise').then((resp) => resp.json()), - })) - expectTypeOf(fromPromiseAnyQueryFn.data()).toEqualTypeOf() - - const getMyDataStringKey: QueryFunction = (context) => { - expectTypeOf(context.queryKey).toEqualTypeOf<['1']>() - return Number(context.queryKey[0]) + 42 - } - - const fromGetMyDataStringKeyQueryFn = injectQuery(() => ({ - queryKey: ['1'] as ['1'], - queryFn: getMyDataStringKey, - })) - expectTypeOf(fromGetMyDataStringKeyQueryFn.data()).toEqualTypeOf< - number | undefined - >() - - // handles wrapped queries with custom fetcher passed as inline queryFn - const createWrappedQuery = < - TQueryKey extends [string, Record?], - TQueryFnData, - TError, - TData = TQueryFnData, - >( - qk: TQueryKey, - fetcher: ( - obj: TQueryKey[1], - token: string, - // return type must be wrapped with TQueryFnReturn - ) => Promise, - options?: OmitKeyof< - CreateQueryOptions, - 'queryKey' | 'queryFn' | 'initialData', - 'safely' - >, - ) => - injectQuery(() => ({ - queryKey: qk, - queryFn: () => fetcher(qk[1], 'token'), - ...options, - })) - const fromWrappedQuery = createWrappedQuery([''], () => - Promise.resolve('1'), - ) - expectTypeOf(fromWrappedQuery.data()).toEqualTypeOf() - - // handles wrapped queries with custom fetcher passed directly to createQuery - const createWrappedFuncStyleQuery = < - TQueryKey extends [string, Record?], - TQueryFnData, - TError, - TData = TQueryFnData, - >( - qk: TQueryKey, - fetcher: () => Promise, - options?: OmitKeyof< - CreateQueryOptions, - 'queryKey' | 'queryFn' | 'initialData', - 'safely' - >, - ) => injectQuery(() => ({ queryKey: qk, queryFn: fetcher, ...options })) - const fromWrappedFuncStyleQuery = createWrappedFuncStyleQuery([''], () => - Promise.resolve(true), - ) - expectTypeOf(fromWrappedFuncStyleQuery.data()).toEqualTypeOf< - boolean | undefined - >() - }) - - describe('initialData', () => { - describe('Config object overload', () => { - it('TData should always be defined when initialData is provided as an object', () => { - const key = queryKey() - const { data } = injectQuery(() => ({ - queryKey: key, - queryFn: () => ({ wow: true }), - initialData: { wow: true }, - })) - - expectTypeOf(data).toEqualTypeOf>() - }) - - it('TData should be defined when passed through queryOptions', () => { - const key = queryKey() - const options = () => - queryOptions({ - queryKey: key, - queryFn: () => { - return { - wow: true, - } - }, - initialData: { - wow: true, - }, - }) - const { data } = injectQuery(options) - - expectTypeOf(data).toEqualTypeOf>() - }) - - it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => { - const key = queryKey() - const options = queryOptions({ - queryKey: key, - queryFn: () => Promise.resolve(1), - }) - - const query = injectQuery(() => ({ - ...options, - select: (data) => data > 1, - })) - - expectTypeOf(query.data).toEqualTypeOf>() - }) - - it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => { - const key = queryKey() - const { data } = injectQuery(() => ({ - queryKey: key, - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => ({ - wow: true, - }), - })) - - expectTypeOf(data).toEqualTypeOf>() - }) - - it('TData should have undefined in the union when initialData is NOT provided', () => { - const key = queryKey() - const { data } = injectQuery(() => ({ - queryKey: key, - queryFn: () => { - return { - wow: true, - } - }, - })) - - expectTypeOf(data).toEqualTypeOf>() - }) - - it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { - const key = queryKey() - const { data } = injectQuery(() => ({ - queryKey: key, - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => undefined as { wow: boolean } | undefined, - })) - - expectTypeOf(data).toEqualTypeOf>() - }) - - it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => { - const key = queryKey() - const query = injectQuery(() => ({ - queryKey: key, - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => undefined as { wow: boolean } | undefined, - })) - - if (query.isSuccess()) { - expectTypeOf(query.data).toEqualTypeOf>() - } - }) - }) - - describe('structuralSharing', () => { - it('should be able to use structuralSharing with unknown types', () => { - const key = queryKey() - // https://github.com/TanStack/query/issues/6525#issuecomment-1938411343 - injectQuery(() => ({ - queryKey: key, - queryFn: () => 5, - structuralSharing: (oldData, newData) => { - expectTypeOf(oldData).toBeUnknown() - expectTypeOf(newData).toBeUnknown() - return newData - }, - })) - }) - }) - }) - - describe('Discriminated union return type', () => { - it('data should be possibly undefined by default', () => { - const key = queryKey() - const query = injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(0).then(() => 'Some data'), - })) - - expectTypeOf(query.data).toEqualTypeOf>() - }) - - it('data should be defined when query is success', () => { - const key = queryKey() - const query = injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(0).then(() => 'Some data'), - })) - - if (query.isSuccess()) { - expectTypeOf(query.data).toEqualTypeOf>() - } - }) - - it('error should be null when query is success', () => { - const key = queryKey() - const query = injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(0).then(() => 'Some data'), - })) - - if (query.isSuccess()) { - expectTypeOf(query.error).toEqualTypeOf>() - } - }) - - it('data should be undefined when query is pending', () => { - const key = queryKey() - const query = injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(0).then(() => 'Some data'), - })) - - if (query.isPending()) { - expectTypeOf(query.data).toEqualTypeOf>() - } - }) - - it('error should be defined when query is error', () => { - const key = queryKey() - const query = injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(0).then(() => 'Some data'), - })) - - if (query.isError()) { - expectTypeOf(query.error).toEqualTypeOf>() - } - }) - }) -}) diff --git a/packages/angular-query-experimental/src/__tests__/inject-query.test.ts b/packages/angular-query-experimental/src/__tests__/inject-query.test.ts deleted file mode 100644 index c36aa0d1ff7..00000000000 --- a/packages/angular-query-experimental/src/__tests__/inject-query.test.ts +++ /dev/null @@ -1,700 +0,0 @@ -import { - ApplicationRef, - Component, - Injector, - computed, - input, - provideZonelessChangeDetection, - signal, -} from '@angular/core' -import { TestBed } from '@angular/core/testing' -import { HttpClient, provideHttpClient } from '@angular/common/http' -import { - HttpTestingController, - provideHttpClientTesting, -} from '@angular/common/http/testing' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { render } from '@testing-library/angular' -import { queryKey, sleep } from '@tanstack/query-test-utils' -import { lastValueFrom } from 'rxjs' -import { - QueryCache, - QueryClient, - injectQuery, - provideIsRestoring, - provideTanStackQuery, -} from '..' -import { setSignalInputs } from './test-utils' - -describe('injectQuery', () => { - let queryCache: QueryCache - let queryClient: QueryClient - - beforeEach(() => { - vi.useFakeTimers() - queryCache = new QueryCache() - queryClient = new QueryClient({ queryCache }) - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), - ], - }) - }) - - afterEach(() => { - vi.useRealTimers() - }) - - it('should return pending status initially', () => { - const key = queryKey() - const query = TestBed.runInInjectionContext(() => { - return injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(10).then(() => 'Some data'), - })) - }) - - expect(query.status()).toBe('pending') - expect(query.isPending()).toBe(true) - expect(query.isFetching()).toBe(true) - expect(query.isStale()).toBe(true) - expect(query.isFetched()).toBe(false) - }) - - it('should resolve to success and update signal: injectQuery()', async () => { - const key = queryKey() - - @Component({ - template: ` -
status: {{ query.status() }}
-
data: {{ query.data() ?? 'none' }}
-
isPending: {{ query.isPending() }}
-
isFetching: {{ query.isFetching() }}
-
isFetched: {{ query.isFetched() }}
-
isSuccess: {{ query.isSuccess() }}
- `, - }) - class Page { - readonly query = injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(10).then(() => 'result2'), - })) - } - - const rendered = await render(Page) - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - - expect(rendered.getByText('status: success')).toBeInTheDocument() - expect(rendered.getByText('data: result2')).toBeInTheDocument() - expect(rendered.getByText('isPending: false')).toBeInTheDocument() - expect(rendered.getByText('isFetching: false')).toBeInTheDocument() - expect(rendered.getByText('isFetched: true')).toBeInTheDocument() - expect(rendered.getByText('isSuccess: true')).toBeInTheDocument() - }) - - it('should reject and update signal', async () => { - const key = queryKey() - - @Component({ - template: ` -
status: {{ query.status() }}
-
data: {{ query.data() ?? 'none' }}
-
error: {{ query.error()?.message ?? 'none' }}
-
isPending: {{ query.isPending() }}
-
isFetching: {{ query.isFetching() }}
-
isError: {{ query.isError() }}
-
failureCount: {{ query.failureCount() }}
-
failureReason: {{ query.failureReason()?.message ?? 'none' }}
- `, - }) - class Page { - readonly query = injectQuery(() => ({ - retry: false, - queryKey: key, - queryFn: () => - sleep(10).then(() => Promise.reject(new Error('Some error'))), - })) - } - - const rendered = await render(Page) - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - - expect(rendered.getByText('status: error')).toBeInTheDocument() - expect(rendered.getByText('data: none')).toBeInTheDocument() - expect(rendered.getByText('error: Some error')).toBeInTheDocument() - expect(rendered.getByText('isPending: false')).toBeInTheDocument() - expect(rendered.getByText('isFetching: false')).toBeInTheDocument() - expect(rendered.getByText('isError: true')).toBeInTheDocument() - expect(rendered.getByText('failureCount: 1')).toBeInTheDocument() - expect(rendered.getByText('failureReason: Some error')).toBeInTheDocument() - }) - - it('should be able to select a part of the data with select', async () => { - const key = queryKey() - - @Component({ - template: `
data: {{ query.data() ?? 'none' }}
`, - }) - class Page { - readonly query = injectQuery<{ name: string }, Error, string>(() => ({ - queryKey: key, - queryFn: () => sleep(10).then(() => ({ name: 'test' })), - select: (data) => data.name, - })) - } - - const rendered = await render(Page) - - expect(rendered.getByText('data: none')).toBeInTheDocument() - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - - expect(rendered.getByText('data: test')).toBeInTheDocument() - }) - - it('should show placeholderData until queryFn resolves and then expose real data', async () => { - const key = queryKey() - - @Component({ - template: ` -
data: {{ query.data() }}
-
isPlaceholderData: {{ query.isPlaceholderData() }}
-
isSuccess: {{ query.isSuccess() }}
- `, - }) - class Page { - readonly query = injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(10).then(() => 'real-data'), - placeholderData: 'placeholder', - })) - } - - const rendered = await render(Page) - - expect(rendered.getByText('data: placeholder')).toBeInTheDocument() - expect(rendered.getByText('isPlaceholderData: true')).toBeInTheDocument() - expect(rendered.getByText('isSuccess: true')).toBeInTheDocument() - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - - expect(rendered.getByText('data: real-data')).toBeInTheDocument() - expect(rendered.getByText('isPlaceholderData: false')).toBeInTheDocument() - expect(rendered.getByText('isSuccess: true')).toBeInTheDocument() - }) - - it('should update query on options contained signal change', async () => { - const key1 = queryKey() - const key2 = queryKey() - const key = signal(key1) - const spy = vi.fn(() => sleep(10).then(() => 'Some data')) - - const query = TestBed.runInInjectionContext(() => { - return injectQuery(() => ({ - queryKey: key(), - queryFn: spy, - })) - }) - - await vi.advanceTimersByTimeAsync(0) - expect(spy).toHaveBeenCalledTimes(1) - - await vi.advanceTimersByTimeAsync(10) - expect(query.status()).toBe('success') - - key.set(key2) - TestBed.tick() - - expect(spy).toHaveBeenCalledTimes(2) - // should call queryFn with context containing the new queryKey - expect(spy).toHaveBeenNthCalledWith(2, { - client: queryClient, - meta: undefined, - queryKey: key2, - signal: expect.anything(), - }) - }) - - it('should only run query once enabled signal is set to true', async () => { - const key = queryKey() - const spy = vi.fn(() => sleep(10).then(() => 'Some data')) - const enabled = signal(false) - - const query = TestBed.runInInjectionContext(() => { - return injectQuery(() => ({ - queryKey: key, - queryFn: spy, - enabled: enabled(), - })) - }) - - expect(spy).not.toHaveBeenCalled() - expect(query.status()).toBe('pending') - - enabled.set(true) - - await vi.advanceTimersByTimeAsync(10) - expect(spy).toHaveBeenCalledTimes(1) - expect(query.status()).toBe('success') - }) - - it('should not fetch while the enabled signal is false, and fetch again once it is truthy', async () => { - const key = queryKey() - const spy = vi.fn(() => sleep(10).then(() => 'Some data')) - const filter = signal('a') - - const query = TestBed.runInInjectionContext(() => { - return injectQuery(() => ({ - queryKey: [...key, filter()], - queryFn: spy, - enabled: !!filter(), - })) - }) - - await vi.advanceTimersByTimeAsync(10) - expect(spy).toHaveBeenCalledTimes(1) - expect(query.status()).toBe('success') - - filter.set('') - - await vi.advanceTimersByTimeAsync(10) - expect(spy).toHaveBeenCalledTimes(1) - expect(query.isFetching()).toBe(false) - - filter.set('b') - - await vi.advanceTimersByTimeAsync(10) - expect(spy).toHaveBeenCalledTimes(2) - }) - - it('should properly execute dependent queries', async () => { - const key1 = queryKey() - const key2 = queryKey() - - const query1 = TestBed.runInInjectionContext(() => { - return injectQuery(() => ({ - queryKey: key1, - queryFn: () => sleep(10).then(() => 'Some data'), - })) - }) - - const dependentQueryFn = vi - .fn() - .mockImplementation(() => sleep(1000).then(() => 'Some data')) - - const query2 = TestBed.runInInjectionContext(() => { - return injectQuery( - computed(() => ({ - queryKey: key2, - queryFn: dependentQueryFn, - enabled: !!query1.data(), - })), - ) - }) - - expect(query1.data()).toStrictEqual(undefined) - expect(query2.fetchStatus()).toStrictEqual('idle') - expect(dependentQueryFn).not.toHaveBeenCalled() - - await vi.advanceTimersByTimeAsync(11) - - expect(query1.data()).toStrictEqual('Some data') - expect(query2.fetchStatus()).toStrictEqual('fetching') - - await vi.advanceTimersByTimeAsync(1002) - - expect(query2.fetchStatus()).toStrictEqual('idle') - expect(query2.status()).toStrictEqual('success') - expect(dependentQueryFn).toHaveBeenCalledTimes(1) - expect(dependentQueryFn).toHaveBeenCalledWith( - expect.objectContaining({ queryKey: key2 }), - ) - }) - - it('should use the current value for the queryKey when refetch is called', async () => { - const key = queryKey() - const fetchFn = vi.fn(() => sleep(10).then(() => 'Some data')) - const keySignal = signal('key11') - - const query = TestBed.runInInjectionContext(() => { - return injectQuery(() => ({ - queryKey: [...key, keySignal()], - queryFn: fetchFn, - enabled: false, - })) - }) - - expect(fetchFn).not.toHaveBeenCalled() - - void query.refetch() - await vi.advanceTimersByTimeAsync(10) - - expect(fetchFn).toHaveBeenCalledTimes(1) - expect(fetchFn).toHaveBeenNthCalledWith( - 1, - expect.objectContaining({ - queryKey: [...key, 'key11'], - }), - ) - - keySignal.set('key12') - - void query.refetch() - await vi.advanceTimersByTimeAsync(10) - - expect(fetchFn).toHaveBeenCalledTimes(2) - expect(fetchFn).toHaveBeenNthCalledWith( - 2, - expect.objectContaining({ - queryKey: [...key, 'key12'], - }), - ) - expect(query.data()).toBe('Some data') - }) - - it('should keep initialData visible alongside the error when a refetch fails', async () => { - const key = queryKey() - - @Component({ - template: ` -
data: {{ query.data() }}
-
isError: {{ query.isError() }}
- `, - }) - class Page { - readonly query = injectQuery(() => ({ - queryKey: key, - queryFn: () => - sleep(10).then(() => Promise.reject(new Error('Some error'))), - initialData: 'initial', - retry: false, - })) - } - - const rendered = await render(Page) - - expect(rendered.getByText('data: initial')).toBeInTheDocument() - expect(rendered.getByText('isError: false')).toBeInTheDocument() - - await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - expect(rendered.getByText('data: initial')).toBeInTheDocument() - expect(rendered.getByText('isError: true')).toBeInTheDocument() - }) - - describe('throwOnError', () => { - it('should evaluate throwOnError when query is expected to throw', async () => { - const key = queryKey() - const boundaryFn = vi.fn() - TestBed.runInInjectionContext(() => { - return injectQuery(() => ({ - queryKey: key, - queryFn: () => - sleep(10).then(() => Promise.reject(new Error('Some error'))), - retry: false, - throwOnError: boundaryFn, - })) - }) - - await vi.advanceTimersByTimeAsync(11) - expect(boundaryFn).toHaveBeenCalledTimes(1) - expect(boundaryFn).toHaveBeenCalledWith( - Error('Some error'), - expect.objectContaining({ - state: expect.objectContaining({ status: 'error' }), - }), - ) - }) - - it('should throw when throwOnError is true', async () => { - const key = queryKey() - TestBed.runInInjectionContext(() => { - return injectQuery(() => ({ - queryKey: key, - queryFn: () => - sleep(0).then(() => Promise.reject(new Error('Some error'))), - throwOnError: true, - })) - }) - - await expect(vi.runAllTimersAsync()).rejects.toThrow('Some error') - }) - - it('should throw when throwOnError function returns true', async () => { - const key = queryKey() - TestBed.runInInjectionContext(() => { - return injectQuery(() => ({ - queryKey: key, - queryFn: () => - sleep(0).then(() => Promise.reject(new Error('Some error'))), - throwOnError: () => true, - })) - }) - - await expect(vi.runAllTimersAsync()).rejects.toThrow('Some error') - }) - }) - - it('should render with required signal inputs', async () => { - @Component({ - selector: 'app-fake', - template: `{{ query.data() }}`, - }) - class FakeComponent { - name = input.required() - - query = injectQuery(() => ({ - queryKey: ['fake', this.name()], - queryFn: () => this.name(), - })) - } - - const fixture = TestBed.createComponent(FakeComponent) - setSignalInputs(fixture.componentInstance, { - name: 'signal-input-required-test', - }) - - fixture.detectChanges() - await vi.advanceTimersByTimeAsync(0) - - expect(fixture.componentInstance.query.data()).toEqual( - 'signal-input-required-test', - ) - }) - - describe('isRestoring', () => { - it('should not fetch for the duration of the restoring period when isRestoring is true', async () => { - const key = queryKey() - const queryFn = vi - .fn() - .mockImplementation(() => sleep(10).then(() => 'data')) - - TestBed.configureTestingModule({ - providers: [provideIsRestoring(signal(true).asReadonly())], - }) - - const query = TestBed.runInInjectionContext(() => - injectQuery(() => ({ - queryKey: key, - queryFn, - })), - ) - - await vi.advanceTimersByTimeAsync(0) - expect(query.status()).toBe('pending') - expect(query.fetchStatus()).toBe('idle') - expect(query.data()).toBeUndefined() - expect(queryFn).toHaveBeenCalledTimes(0) - - await vi.advanceTimersByTimeAsync(10) - expect(query.status()).toBe('pending') - expect(query.fetchStatus()).toBe('idle') - expect(query.data()).toBeUndefined() - expect(queryFn).toHaveBeenCalledTimes(0) - }) - }) - - describe('injection context', () => { - it('should throw NG0203 with descriptive error outside injection context', () => { - const key = queryKey() - expect(() => { - injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(0).then(() => 'Some data'), - })) - }).toThrow(/NG0203(.*?)injectQuery/) - }) - - it('should be usable outside injection context when passing an injector', () => { - const key = queryKey() - const query = injectQuery( - () => ({ - queryKey: key, - queryFn: () => sleep(0).then(() => 'Some data'), - }), - { - injector: TestBed.inject(Injector), - }, - ) - - expect(query.status()).toBe('pending') - }) - - it('should complete queries before whenStable() resolves', async () => { - const key = queryKey() - const app = TestBed.inject(ApplicationRef) - - const query = TestBed.runInInjectionContext(() => - injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(50).then(() => 'test data'), - })), - ) - - expect(query.status()).toBe('pending') - expect(query.data()).toBeUndefined() - - const stablePromise = app.whenStable() - await vi.advanceTimersByTimeAsync(60) - await stablePromise - - expect(query.status()).toBe('success') - expect(query.data()).toBe('test data') - }) - - it('should complete HttpClient-based queries before whenStable() resolves', async () => { - TestBed.configureTestingModule({ - providers: [provideHttpClient(), provideHttpClientTesting()], - }) - - const app = TestBed.inject(ApplicationRef) - const httpClient = TestBed.inject(HttpClient) - const httpTestingController = TestBed.inject(HttpTestingController) - - // Create a query using HttpClient - const key = queryKey() - const query = TestBed.runInInjectionContext(() => - injectQuery(() => ({ - queryKey: key, - queryFn: () => - lastValueFrom(httpClient.get<{ message: string }>('/api/test')), - })), - ) - - // Schedule the HTTP response - setTimeout(() => { - const req = httpTestingController.expectOne('/api/test') - req.flush({ message: 'http test data' }) - }, 10) - - // Initial state - expect(query.status()).toBe('pending') - - // Advance timers and wait for Angular to be "stable" - const stablePromise = app.whenStable() - await vi.advanceTimersByTimeAsync(20) - await stablePromise - - // Query should be complete after whenStable() thanks to PendingTasks integration - expect(query.status()).toBe('success') - expect(query.data()).toEqual({ message: 'http test data' }) - - httpTestingController.verify() - }) - - it('should handle synchronous queryFn with staleTime', async () => { - const app = TestBed.inject(ApplicationRef) - let callCount = 0 - - const key = queryKey() - const query = TestBed.runInInjectionContext(() => - injectQuery(() => ({ - queryKey: key, - staleTime: 1000, - queryFn: () => { - callCount++ - return `sync-data-${callCount}` - }, - })), - ) - - // Synchronize pending effects - TestBed.tick() - - const stablePromise = app.whenStable() - await stablePromise - - expect(query.status()).toBe('success') - expect(query.data()).toBe('sync-data-1') - expect(callCount).toBe(1) - - await query.refetch() - await Promise.resolve() - await vi.runAllTimersAsync() - await app.whenStable() - - expect(query.status()).toBe('success') - expect(query.data()).toBe('sync-data-2') - expect(callCount).toBe(2) - }) - - it('should handle enabled/disabled transitions with synchronous queryFn', async () => { - const app = TestBed.inject(ApplicationRef) - const enabledSignal = signal(false) - let callCount = 0 - - const key = queryKey() - const query = TestBed.runInInjectionContext(() => - injectQuery(() => ({ - queryKey: key, - enabled: enabledSignal(), - queryFn: () => { - callCount++ - return `sync-data-${callCount}` - }, - })), - ) - - // Initially disabled - TestBed.tick() - await app.whenStable() - expect(query.status()).toBe('pending') - expect(query.data()).toBeUndefined() - expect(callCount).toBe(0) - - // Enable the query - enabledSignal.set(true) - TestBed.tick() - - await app.whenStable() - expect(query.status()).toBe('success') - expect(query.data()).toBe('sync-data-1') - expect(callCount).toBe(1) - }) - - it('should handle query invalidation with synchronous data', async () => { - const app = TestBed.inject(ApplicationRef) - const testKey = queryKey() - let callCount = 0 - - const query = TestBed.runInInjectionContext(() => - injectQuery(() => ({ - queryKey: testKey, - queryFn: () => { - callCount++ - return `sync-data-${callCount}` - }, - })), - ) - - // Synchronize pending effects - TestBed.tick() - - await app.whenStable() - expect(query.status()).toBe('success') - expect(query.data()).toBe('sync-data-1') - expect(callCount).toBe(1) - - // Invalidate the query - queryClient.invalidateQueries({ queryKey: testKey }) - TestBed.tick() - - // Wait for the invalidation to trigger a refetch - await Promise.resolve() - await vi.advanceTimersByTimeAsync(10) - TestBed.tick() - - await app.whenStable() - expect(query.status()).toBe('success') - expect(query.data()).toBe('sync-data-2') - expect(callCount).toBe(2) - }) - }) -}) diff --git a/packages/angular-query-experimental/src/__tests__/provide-query-client.test.ts b/packages/angular-query-experimental/src/__tests__/provide-query-client.test.ts deleted file mode 100644 index 5253274de34..00000000000 --- a/packages/angular-query-experimental/src/__tests__/provide-query-client.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { TestBed } from '@angular/core/testing' -import { describe, expect, it } from 'vitest' -import { InjectionToken, provideZonelessChangeDetection } from '@angular/core' -import { QueryClient } from '@tanstack/query-core' -import { provideQueryClient } from '../providers' - -describe('provideQueryClient', () => { - it('should provide a QueryClient instance directly', () => { - const queryClient = new QueryClient() - - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideQueryClient(queryClient), - ], - }) - - const providedQueryClient = TestBed.inject(QueryClient) - expect(providedQueryClient).toBe(queryClient) - }) - - it('should provide a QueryClient instance using an InjectionToken', () => { - const queryClient = new QueryClient() - const CUSTOM_QUERY_CLIENT = new InjectionToken('', { - factory: () => queryClient, - }) - - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideQueryClient(CUSTOM_QUERY_CLIENT), - ], - }) - - const providedQueryClient = TestBed.inject(QueryClient) - expect(providedQueryClient).toBe(queryClient) - }) -}) diff --git a/packages/angular-query-experimental/src/__tests__/provide-tanstack-query.test.ts b/packages/angular-query-experimental/src/__tests__/provide-tanstack-query.test.ts deleted file mode 100644 index ff1cf4324fc..00000000000 --- a/packages/angular-query-experimental/src/__tests__/provide-tanstack-query.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { TestBed } from '@angular/core/testing' -import { describe, expect, it } from 'vitest' -import { InjectionToken, provideZonelessChangeDetection } from '@angular/core' -import { QueryClient } from '@tanstack/query-core' -import { provideTanStackQuery } from '../providers' - -describe('provideTanStackQuery', () => { - it('should provide a QueryClient instance directly', () => { - const queryClient = new QueryClient() - - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), - ], - }) - - const providedQueryClient = TestBed.inject(QueryClient) - expect(providedQueryClient).toBe(queryClient) - }) - - it('should provide a QueryClient instance using an InjectionToken', () => { - const queryClient = new QueryClient() - const CUSTOM_QUERY_CLIENT = new InjectionToken('', { - factory: () => queryClient, - }) - - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(CUSTOM_QUERY_CLIENT), - ], - }) - - const providedQueryClient = TestBed.inject(QueryClient) - expect(providedQueryClient).toBe(queryClient) - }) -}) diff --git a/packages/angular-query-experimental/src/__tests__/signal-proxy.test.ts b/packages/angular-query-experimental/src/__tests__/signal-proxy.test.ts deleted file mode 100644 index cebcd7b82bb..00000000000 --- a/packages/angular-query-experimental/src/__tests__/signal-proxy.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { isSignal, signal } from '@angular/core' -import { describe, expect, it } from 'vitest' -import { signalProxy } from '../signal-proxy' - -describe('signalProxy', () => { - const inputSignal = signal({ fn: () => 'bar', baz: 'qux' }) - const proxy = signalProxy(inputSignal) - - it('should have computed fields', () => { - expect(proxy.baz()).toEqual('qux') - expect(isSignal(proxy.baz)).toBe(true) - }) - - it('should pass through functions as-is', () => { - expect(proxy.fn()).toEqual('bar') - expect(isSignal(proxy.fn)).toBe(false) - }) - - it('should support "in" operator', () => { - expect('baz' in proxy).toBe(true) - expect('foo' in proxy).toBe(false) - }) - - it('should support "Object.keys"', () => { - expect(Object.keys(proxy)).toEqual(['fn', 'baz']) - }) -}) diff --git a/packages/angular-query-experimental/src/__tests__/test-utils.ts b/packages/angular-query-experimental/src/__tests__/test-utils.ts deleted file mode 100644 index 218cdea5f6c..00000000000 --- a/packages/angular-query-experimental/src/__tests__/test-utils.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { isSignal, untracked } from '@angular/core' -import { SIGNAL, signalSetFn } from '@angular/core/primitives/signals' -import { expect } from 'vitest' -import type { InputSignal, Signal } from '@angular/core' -import type { ComponentFixture } from '@angular/core/testing' - -// Evaluate all signals on an object and return the result -function evaluateSignals>( - obj: T, -): { [K in keyof T]: ReturnType } { - const result: Partial<{ [K in keyof T]: ReturnType }> = {} - - untracked(() => { - for (const key in obj) { - if ( - Object.prototype.hasOwnProperty.call(obj, key) && - // Only evaluate signals, not normal functions - isSignal(obj[key]) - ) { - const func = obj[key] - result[key] = func() - } - } - }) - - return result as { [K in keyof T]: ReturnType } -} - -export const expectSignals = >( - obj: T, - expected: Partial<{ - [K in keyof T]: T[K] extends Signal ? ReturnType : never - }>, -): void => { - expect(evaluateSignals(obj)).toMatchObject(expected) -} - -type ToSignalInputUpdatableMap = { - [K in keyof T as T[K] extends InputSignal - ? K - : never]: T[K] extends InputSignal ? Value : never -} - -function componentHasSignalInputProperty( - component: object, - property: TProperty, -): component is { [key in TProperty]: InputSignal } { - return ( - component.hasOwnProperty(property) && (component as any)[property][SIGNAL] - ) -} - -/** - * Set required signal input value to component fixture - * @see https://github.com/angular/angular/issues/54013 - */ -export function setSignalInputs>( - component: T, - inputs: ToSignalInputUpdatableMap, -) { - for (const inputKey in inputs) { - if (componentHasSignalInputProperty(component, inputKey)) { - signalSetFn(component[inputKey][SIGNAL], inputs[inputKey]) - } - } -} - -export function setFixtureSignalInputs>( - componentFixture: ComponentFixture, - inputs: ToSignalInputUpdatableMap, - options: { detectChanges: boolean } = { detectChanges: true }, -) { - setSignalInputs(componentFixture.componentInstance, inputs) - if (options.detectChanges) { - componentFixture.detectChanges() - } -} diff --git a/packages/angular-query-experimental/src/create-base-query.ts b/packages/angular-query-experimental/src/create-base-query.ts deleted file mode 100644 index 4daede76844..00000000000 --- a/packages/angular-query-experimental/src/create-base-query.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { - NgZone, - VERSION, - computed, - effect, - inject, - signal, - untracked, -} from '@angular/core' -import { - QueryClient, - notifyManager, - shouldThrowError, -} from '@tanstack/query-core' -import { signalProxy } from './signal-proxy' -import { injectIsRestoring } from './inject-is-restoring' -import { PENDING_TASKS } from './pending-tasks-compat' -import type { PendingTaskRef } from './pending-tasks-compat' -import type { - QueryKey, - QueryObserver, - QueryObserverResult, -} from '@tanstack/query-core' -import type { CreateBaseQueryOptions } from './types' - -/** - * Base implementation for `injectQuery` and `injectInfiniteQuery`. - * @param optionsFn - * @param Observer - */ -export function createBaseQuery< - TQueryFnData, - TError, - TData, - TQueryData, - TQueryKey extends QueryKey, ->( - optionsFn: () => CreateBaseQueryOptions< - TQueryFnData, - TError, - TData, - TQueryData, - TQueryKey - >, - Observer: typeof QueryObserver, -) { - const ngZone = inject(NgZone) - const pendingTasks = inject(PENDING_TASKS) - const queryClient = inject(QueryClient) - const isRestoring = injectIsRestoring() - - /** - * Signal that has the default options from query client applied - * computed() is used so signals can be inserted into the options - * making it reactive. Wrapping options in a function ensures embedded expressions - * are preserved and can keep being applied after signal changes - */ - const defaultedOptionsSignal = computed(() => { - const defaultedOptions = queryClient.defaultQueryOptions(optionsFn()) - defaultedOptions._optimisticResults = isRestoring() - ? 'isRestoring' - : 'optimistic' - return defaultedOptions - }) - - const observerSignal = (() => { - let instance: QueryObserver< - TQueryFnData, - TError, - TData, - TQueryData, - TQueryKey - > | null = null - - return computed(() => { - return (instance ||= new Observer(queryClient, defaultedOptionsSignal())) - }) - })() - - const optimisticResultSignal = computed(() => - observerSignal().getOptimisticResult(defaultedOptionsSignal()), - ) - - const resultFromSubscriberSignal = signal | null>(null) - - effect( - (onCleanup) => { - const observer = observerSignal() - const defaultedOptions = defaultedOptionsSignal() - - untracked(() => { - observer.setOptions(defaultedOptions) - }) - onCleanup(() => { - ngZone.run(() => resultFromSubscriberSignal.set(null)) - }) - }, - { - // Set allowSignalWrites to support Angular < v19 - // Set to undefined to avoid warning on newer versions - allowSignalWrites: VERSION.major < '19' || undefined, - }, - ) - - effect((onCleanup) => { - // observer.trackResult is not used as this optimization is not needed for Angular - const observer = observerSignal() - let pendingTaskRef: PendingTaskRef | null = null - - const unsubscribe = isRestoring() - ? () => undefined - : untracked(() => - ngZone.runOutsideAngular(() => { - return observer.subscribe( - notifyManager.batchCalls((state) => { - ngZone.run(() => { - if (state.fetchStatus === 'fetching' && !pendingTaskRef) { - pendingTaskRef = pendingTasks.add() - } - - if (state.fetchStatus === 'idle' && pendingTaskRef) { - pendingTaskRef() - pendingTaskRef = null - } - - if ( - state.isError && - !state.isFetching && - shouldThrowError(observer.options.throwOnError, [ - state.error, - observer.getCurrentQuery(), - ]) - ) { - ngZone.onError.emit(state.error) - throw state.error - } - resultFromSubscriberSignal.set(state) - }) - }), - ) - }), - ) - - onCleanup(() => { - if (pendingTaskRef) { - pendingTaskRef() - pendingTaskRef = null - } - unsubscribe() - }) - }) - - return signalProxy( - computed(() => { - const subscriberResult = resultFromSubscriberSignal() - const optimisticResult = optimisticResultSignal() - const result = subscriberResult ?? optimisticResult - - // Wrap methods to ensure observer has latest options before execution - const observer = observerSignal() - - const originalRefetch = result.refetch - return { - ...result, - refetch: ((...args: Parameters) => { - observer.setOptions(defaultedOptionsSignal()) - return originalRefetch(...args) - }) as typeof originalRefetch, - } - }), - ) -} diff --git a/packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts b/packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts deleted file mode 100644 index 94aaa185ca7..00000000000 --- a/packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { - DestroyRef, - Injector, - PLATFORM_ID, - assertInInjectionContext, - computed, - effect, - inject, - runInInjectionContext, - untracked, -} from '@angular/core' -import { QueryClient, onlineManager } from '@tanstack/query-core' -import { isPlatformBrowser } from '@angular/common' -import type { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools' -import type { - DevtoolsPanelOptions, - InjectDevtoolsPanel, - InjectDevtoolsPanelOptions, -} from './types' - -/** - * Inject a TanStack Query devtools panel and render it in the DOM. - * - * Devtools panel allows programmatic control over the devtools, for example if you want to render - * the devtools as part of your own devtools. - * - * Consider `withDevtools` instead if you don't need this. - * @param injectDevtoolsPanelFn - A function that returns devtools panel options. - * @param options - Additional configuration - * @returns DevtoolsPanelRef - * @see https://tanstack.com/query/v5/docs/framework/angular/devtools - */ -export const injectDevtoolsPanel: InjectDevtoolsPanel = ( - injectDevtoolsPanelFn: () => DevtoolsPanelOptions, - options?: InjectDevtoolsPanelOptions, -) => { - !options?.injector && assertInInjectionContext(injectDevtoolsPanel) - const currentInjector = options?.injector ?? inject(Injector) - - return runInInjectionContext(currentInjector, () => { - const destroyRef = inject(DestroyRef) - const isBrowser = isPlatformBrowser(inject(PLATFORM_ID)) - const injectedClient = inject(QueryClient, { optional: true }) - - const queryOptions = computed(injectDevtoolsPanelFn) - let devtools: TanstackQueryDevtoolsPanel | null = null - - const destroy = () => { - devtools?.unmount() - devtools = null - } - - if (!isBrowser) - return { - destroy, - } - - effect(() => { - const { - client = injectedClient, - errorTypes = [], - styleNonce, - shadowDOMTarget, - onClose, - hostElement, - } = queryOptions() - - untracked(() => { - if (!client) throw new Error('No QueryClient found') - if (!devtools && hostElement) { - import('@tanstack/query-devtools') - .then((queryDevtools) => { - devtools = new queryDevtools.TanstackQueryDevtoolsPanel({ - client, - queryFlavor: 'Angular Query', - version: '5', - buttonPosition: 'bottom-left', - position: 'bottom', - initialIsOpen: true, - errorTypes, - styleNonce, - shadowDOMTarget, - onClose, - onlineManager, - }) - devtools.mount(hostElement.nativeElement) - }) - .catch((error) => { - console.error( - 'Install @tanstack/query-devtools or reinstall without --omit=optional.', - error, - ) - }) - } else if (devtools && hostElement) { - devtools.setClient(client) - devtools.setErrorTypes(errorTypes) - onClose && devtools.setOnClose(onClose) - } else if (devtools && !hostElement) { - destroy() - } - }) - }) - - destroyRef.onDestroy(destroy) - - return { - destroy, - } - }) -} diff --git a/packages/angular-query-experimental/src/devtools-panel/production/index.ts b/packages/angular-query-experimental/src/devtools-panel/production/index.ts deleted file mode 100644 index 546becea7f8..00000000000 --- a/packages/angular-query-experimental/src/devtools-panel/production/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from '..' diff --git a/packages/angular-query-experimental/src/devtools/index.ts b/packages/angular-query-experimental/src/devtools/index.ts deleted file mode 100644 index d4f7e9238f7..00000000000 --- a/packages/angular-query-experimental/src/devtools/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type { - DevtoolsOptions, - WithDevtools, - WithDevtoolsFn, - WithDevtoolsOptions, -} from './types' - -export { withDevtools } from './with-devtools' diff --git a/packages/angular-query-experimental/src/devtools/production/index.ts b/packages/angular-query-experimental/src/devtools/production/index.ts deleted file mode 100644 index 546becea7f8..00000000000 --- a/packages/angular-query-experimental/src/devtools/production/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from '..' diff --git a/packages/angular-query-experimental/src/devtools/stub.ts b/packages/angular-query-experimental/src/devtools/stub.ts deleted file mode 100644 index d8090a4b28b..00000000000 --- a/packages/angular-query-experimental/src/devtools/stub.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { WithDevtools } from './types' - -// Stub which replaces `withDevtools` in production builds -export const withDevtools: WithDevtools = () => ({ - ɵkind: 'Devtools', - ɵproviders: [], -}) diff --git a/packages/angular-query-experimental/src/devtools/types.ts b/packages/angular-query-experimental/src/devtools/types.ts deleted file mode 100644 index c2890758011..00000000000 --- a/packages/angular-query-experimental/src/devtools/types.ts +++ /dev/null @@ -1,116 +0,0 @@ -import type { QueryClient } from '@tanstack/query-core' -import type { - DevtoolsButtonPosition, - DevtoolsErrorType, - DevtoolsPosition, - Theme, -} from '@tanstack/query-devtools' -import type { DevtoolsFeature } from '../providers' - -/** - * Options for configuring withDevtools. - */ -export interface WithDevtoolsOptions { - /** - * An array of dependencies to be injected and passed to the `withDevtoolsFn` function. - * - * **Example** - * ```ts - * export const appConfig: ApplicationConfig = { - * providers: [ - * provideTanStackQuery( - * new QueryClient(), - * withDevtools( - * (devToolsOptionsManager: DevtoolsOptionsManager) => ({ - * loadDevtools: devToolsOptionsManager.loadDevtools(), - * }), - * { - * deps: [DevtoolsOptionsManager], - * }, - * ), - * ), - * ], - * } - * ``` - */ - deps?: Array -} - -/** - * Options for configuring the TanStack Query devtools. - */ -export interface DevtoolsOptions { - /** - * Set this true if you want the devtools to default to being open - */ - initialIsOpen?: boolean - /** - * The position of the TanStack logo to open and close the devtools panel. - * `top-left` | `top-right` | `bottom-left` | `bottom-right` | `relative` - * - * @defaultValue bottom-right - */ - buttonPosition?: DevtoolsButtonPosition - /** - * The position of the Angular Query devtools panel. - * `top` | `bottom` | `left` | `right` - * - * @defaultValue bottom - */ - position?: DevtoolsPosition - /** - * Custom instance of QueryClient - */ - client?: QueryClient - /** - * Use this so you can define custom errors that can be shown in the devtools. - */ - errorTypes?: Array - /** - * Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles. - */ - styleNonce?: string - /** - * Use this so you can attach the devtool's styles to a specific element in the DOM. - */ - shadowDOMTarget?: ShadowRoot - /** - * Set this to true to hide disabled queries from the devtools panel. - */ - hideDisabledQueries?: boolean - /** - * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel. - * - * @defaultValue system - */ - theme?: Theme - - /** - * Whether the developer tools should load. - * - `auto`- (Default) Lazily loads devtools when in development mode. Skips loading in production mode. - * - `true`- Always load the devtools, regardless of the environment. - * - `false`- Never load the devtools, regardless of the environment. - * - * You can use `true` and `false` to override loading developer tools from an environment file. - * For example, a test environment might run in production mode but you may want to load developer tools. - * - * Additionally, you can use a signal in the callback to dynamically load the devtools based on a condition. For example, - * a signal created from a RxJS observable that listens for a keyboard shortcut. - * - * **Example** - * ```ts - * withDevtools(() => ({ - * initialIsOpen: true, - * loadDevtools: inject(ExampleService).loadDevtools() - * })) - * ``` - */ - loadDevtools?: 'auto' | boolean -} - -export type WithDevtoolsFn = (...deps: Array) => DevtoolsOptions - -export type WithDevtools = ( - withDevtoolsFn?: WithDevtoolsFn, - options?: WithDevtoolsOptions, -) => DevtoolsFeature diff --git a/packages/angular-query-experimental/src/devtools/with-devtools.ts b/packages/angular-query-experimental/src/devtools/with-devtools.ts deleted file mode 100644 index 4d4b861c7f2..00000000000 --- a/packages/angular-query-experimental/src/devtools/with-devtools.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { isPlatformBrowser } from '@angular/common' -import { - DestroyRef, - ENVIRONMENT_INITIALIZER, - InjectionToken, - Injector, - PLATFORM_ID, - computed, - effect, - inject, - isDevMode, -} from '@angular/core' -import { QueryClient, noop, onlineManager } from '@tanstack/query-core' -import { queryFeature } from '../providers' -import type { Signal } from '@angular/core' -import type { - DevtoolsOptions, - WithDevtools, - WithDevtoolsFn, - WithDevtoolsOptions, -} from './types' -import type { TanstackQueryDevtools } from '@tanstack/query-devtools' - -/** - * Internal token used to prevent double providing of devtools in child injectors - */ -const DEVTOOLS_PROVIDED = new InjectionToken('', { - factory: () => ({ - isProvided: false, - }), -}) - -/** - * Internal token for providing devtools options - */ -const DEVTOOLS_OPTIONS_SIGNAL = new InjectionToken>('') - -/** - * Enables developer tools in Angular development builds. - * - * **Example** - * - * ```ts - * export const appConfig: ApplicationConfig = { - * providers: [ - * provideTanStackQuery(new QueryClient(), withDevtools()) - * ] - * } - * ``` - * The devtools will be rendered in ``. - * - * If you need more control over when devtools are loaded, you can use the `loadDevtools` option. - * - * If you need more control over where devtools are rendered, consider `injectDevtoolsPanel`. This allows rendering devtools inside your own devtools for example. - * @param withDevtoolsFn - A function that returns `DevtoolsOptions`. - * @param options - Additional options for configuring `withDevtools`. - * @returns A set of providers for use with `provideTanStackQuery`. - * @see {@link provideTanStackQuery} - * @see {@link DevtoolsOptions} - */ -export const withDevtools: WithDevtools = ( - withDevtoolsFn?: WithDevtoolsFn, - options: WithDevtoolsOptions = {}, -) => - queryFeature('Devtools', [ - { - provide: DEVTOOLS_OPTIONS_SIGNAL, - useFactory: (...deps: Array) => - computed(() => withDevtoolsFn?.(...deps) ?? {}), - deps: options.deps || [], - }, - { - // Do not use provideEnvironmentInitializer while Angular < v19 is supported - provide: ENVIRONMENT_INITIALIZER, - multi: true, - useFactory: () => { - const devtoolsProvided = inject(DEVTOOLS_PROVIDED) - if ( - !isPlatformBrowser(inject(PLATFORM_ID)) || - devtoolsProvided.isProvided - ) - return noop - - devtoolsProvided.isProvided = true - let injectorIsDestroyed = false - inject(DestroyRef).onDestroy(() => (injectorIsDestroyed = true)) - - return () => { - const injectedClient = inject(QueryClient, { - optional: true, - }) - const destroyRef = inject(DestroyRef) - const devtoolsOptions = inject(DEVTOOLS_OPTIONS_SIGNAL) - const injector = inject(Injector) - - let devtools: TanstackQueryDevtools | null = null - let el: HTMLElement | null = null - - const shouldLoadToolsSignal = computed(() => { - const { loadDevtools } = devtoolsOptions() - return typeof loadDevtools === 'boolean' - ? loadDevtools - : isDevMode() - }) - - const getResolvedQueryClient = () => { - const client = devtoolsOptions().client ?? injectedClient - if (!client) { - throw new Error('No QueryClient found') - } - return client - } - - const destroyDevtools = () => { - devtools?.unmount() - el?.remove() - devtools = null - } - - effect( - () => { - const shouldLoadTools = shouldLoadToolsSignal() - const { - client, - position, - errorTypes, - buttonPosition, - initialIsOpen, - theme, - } = devtoolsOptions() - - if (!shouldLoadTools) { - // Destroy or do nothing - devtools && destroyDevtools() - return - } - - if (devtools) { - // Update existing devtools config - client && devtools.setClient(client) - position && devtools.setPosition(position) - errorTypes && devtools.setErrorTypes(errorTypes) - buttonPosition && devtools.setButtonPosition(buttonPosition) - typeof initialIsOpen === 'boolean' && - devtools.setInitialIsOpen(initialIsOpen) - theme && devtools.setTheme(theme) - return - } - - // Create devtools - import('@tanstack/query-devtools') - .then((queryDevtools) => { - // As this code runs async, the injector could have been destroyed - if (injectorIsDestroyed) return - - devtools = new queryDevtools.TanstackQueryDevtools({ - ...devtoolsOptions(), - client: getResolvedQueryClient(), - queryFlavor: 'Angular Query', - version: '5', - onlineManager, - }) - - el = document.body.appendChild(document.createElement('div')) - el.classList.add('tsqd-parent-container') - devtools.mount(el) - - destroyRef.onDestroy(destroyDevtools) - }) - .catch((error) => { - console.error( - 'Install @tanstack/query-devtools or reinstall without --omit=optional.', - error, - ) - }) - }, - { injector }, - ) - } - }, - }, - ]) diff --git a/packages/angular-query-experimental/src/inject-infinite-query.ts b/packages/angular-query-experimental/src/inject-infinite-query.ts deleted file mode 100644 index a0413075162..00000000000 --- a/packages/angular-query-experimental/src/inject-infinite-query.ts +++ /dev/null @@ -1,296 +0,0 @@ -import { InfiniteQueryObserver } from '@tanstack/query-core' -import { - Injector, - assertInInjectionContext, - inject, - runInInjectionContext, -} from '@angular/core' -import { createBaseQuery } from './create-base-query' -import type { - DefaultError, - InfiniteData, - QueryKey, - QueryObserver, -} from '@tanstack/query-core' -import type { - CreateInfiniteQueryOptions, - CreateInfiniteQueryResult, - DefinedCreateInfiniteQueryResult, -} from './types' -import type { - DefinedInitialDataInfiniteOptions, - UndefinedInitialDataInfiniteOptions, -} from './infinite-query-options' - -export interface InjectInfiniteQueryOptions { - /** - * The `Injector` in which to create the infinite query. - * - * If this is not provided, the current injection context will be used instead (via `inject`). - */ - injector?: Injector -} - -/** - * The options for `injectInfiniteQuery` are identical to `injectQuery`, with the addition of - * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. Infinite queries can - * additively "load more" data onto an existing set of data, or "infinite scroll". - * - * This overload is selected when `initialData` is set on the options returned by `injectInfiniteQueryFn`, - * so the resulting `data` signal is never `undefined` (unless a `select` changes `TData` to include `undefined`). - * - * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default - * refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user - * actions, or add conditions like `hasNextPage() && !isFetching()`. - * @see {@link infiniteQueryOptions} to share these options between `injectInfiniteQuery` and imperative APIs - * like `queryClient.fetchInfiniteQuery`. - * @param injectInfiniteQueryFn - A function returning the {@link DefinedInitialDataInfiniteOptions} to use — - * everything you can pass to `injectInfiniteQuery`, with `initialData` set. Similar to `computed` from - * Angular, this function runs in the reactive context, so signals read inside it drive the query. - * @param options - Additional configuration. - * @returns The same signals as `injectQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, - * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and - * `data().pageParams` are also added, as long as a `select` doesn't change `TData` away from its default - * `InfiniteData` shape. - * - * @example - * ```angular-ts - * @Component({ - * selector: 'projects', - * template: ` - * - *
    - * @for (page of projectsQuery.data().pages; track $index) { - * @for (project of page.projects; track project.id) { - *
  • {{ project.name }}
  • - * } - * } - *
- * `, - * }) - * export class Projects { - * readonly projectsQuery = injectInfiniteQuery(() => ({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * initialData: { pages: [], pageParams: [] }, - * })) - * } - * ``` - */ -export function injectInfiniteQuery< - TQueryFnData, - TError = DefaultError, - TData = InfiniteData, - TQueryKey extends QueryKey = QueryKey, - TPageParam = unknown, ->( - injectInfiniteQueryFn: () => DefinedInitialDataInfiniteOptions< - TQueryFnData, - TError, - TData, - TQueryKey, - TPageParam - >, - options?: InjectInfiniteQueryOptions, -): DefinedCreateInfiniteQueryResult - -/** - * Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a - * unique key. Infinite queries can additively "load more" data onto an existing set of data, or - * "infinite scroll". - * - * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default - * refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user - * actions, or add conditions like `hasNextPage() && !isFetching()`. This is the only overload that accepts - * `queryFn: skipToken`, shown below. - * @see {@link infiniteQueryOptions} to share these options between `injectInfiniteQuery` and imperative APIs - * like `queryClient.fetchInfiniteQuery`. - * @param injectInfiniteQueryFn - A function returning the {@link UndefinedInitialDataInfiniteOptions} to use - * — everything you can pass to `injectInfiniteQuery`. Similar to `computed` from Angular, this function runs - * in the reactive context, so signals read inside it drive the query. - * @param options - Additional configuration. - * @returns The same signals as `injectQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, - * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and - * `data().pageParams` are also added, as long as a `select` doesn't change `TData` away from its default - * `InfiniteData` shape. - * - * @example - * Fetching the next page from a button click: - * ```angular-ts - * @Component({ - * selector: 'projects-list', - * template: ` - *
    - * @for (page of projectsQuery.data()?.pages; track $index) { - * @for (project of page.projects; track project.id) { - *
  • {{ project.name }}
  • - * } - * } - *
- * - * `, - * }) - * export class ProjectsList { - * readonly projectsQuery = injectInfiniteQuery(() => ({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * })) - * } - * ``` - * - * @example - * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a sentinel - * element after the list: - * ```angular-ts - * @Component({ - * selector: 'projects-list', - * template: ` - *
    - * @for (page of projectsQuery.data()?.pages; track $index) { - * @for (project of page.projects; track project.id) { - *
  • {{ project.name }}
  • - * } - * } - *
- *
{{ projectsQuery.isFetchingNextPage() ? 'Loading more...' : '' }}
- * `, - * }) - * export class ProjectsList { - * readonly sentinel = viewChild>('sentinel') - * - * readonly projectsQuery = injectInfiniteQuery(() => ({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * })) - * - * constructor() { - * effect((onCleanup) => { - * const sentinel = this.sentinel()?.nativeElement - * if ( - * sentinel == null || - * !this.projectsQuery.hasNextPage() || - * this.projectsQuery.isFetching() - * ) { - * return - * } - * - * const observer = new IntersectionObserver(([entry]) => { - * if (entry?.isIntersecting) this.projectsQuery.fetchNextPage() - * }) - * observer.observe(sentinel) - * - * onCleanup(() => observer.disconnect()) - * }) - * } - * } - * ``` - * - * @example - * A query that's disabled, type safe, until `postId` is set — pass `skipToken` as `queryFn` instead of - * setting `enabled: false`: - * ```angular-ts - * @Component({ - * selector: 'comments', - * template: ` - * @if (postId() == null) { - * Select a post - * } @else if (commentsQuery.isPending()) { - * Loading... - * } @else if (commentsQuery.isError()) { - * Error: {{ commentsQuery.error()?.message }} - * } @else { - *
    - * @for (page of commentsQuery.data().pages; track $index) { - * @for (comment of page.comments; track comment.id) { - *
  • {{ comment.text }}
  • - * } - * } - *
- * } - * `, - * }) - * export class Comments { - * readonly postId = signal(undefined) - * - * readonly commentsQuery = injectInfiniteQuery(() => ({ - * queryKey: ['post', this.postId(), 'comments'], - * queryFn: - * this.postId() != null - * ? ({ pageParam }) => fetchComments(this.postId()!, pageParam) - * : skipToken, - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * })) - * } - * ``` - */ -export function injectInfiniteQuery< - TQueryFnData, - TError = DefaultError, - TData = InfiniteData, - TQueryKey extends QueryKey = QueryKey, - TPageParam = unknown, ->( - injectInfiniteQueryFn: () => UndefinedInitialDataInfiniteOptions< - TQueryFnData, - TError, - TData, - TQueryKey, - TPageParam - >, - options?: InjectInfiniteQueryOptions, -): CreateInfiniteQueryResult - -/** - * This overload accepts the general {@link CreateInfiniteQueryOptions} shape rather than the - * `initialData`-aware overloads above, so whether `data` is defined can't be inferred from the call site — - * useful when wrapping `injectInfiniteQuery` in your own helper function that forwards caller-provided - * options. - * - * @param injectInfiniteQueryFn - A function that returns infinite query options. Similar to `computed` from - * Angular, this function runs in the reactive context, so signals read inside it drive the query. - * @param options - Additional configuration. - * @returns The infinite query result. - */ -export function injectInfiniteQuery< - TQueryFnData, - TError = DefaultError, - TData = InfiniteData, - TQueryKey extends QueryKey = QueryKey, - TPageParam = unknown, ->( - injectInfiniteQueryFn: () => CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryKey, - TPageParam - >, - options?: InjectInfiniteQueryOptions, -): CreateInfiniteQueryResult - -export function injectInfiniteQuery( - injectInfiniteQueryFn: () => CreateInfiniteQueryOptions, - options?: InjectInfiniteQueryOptions, -) { - !options?.injector && assertInInjectionContext(injectInfiniteQuery) - const injector = options?.injector ?? inject(Injector) - return runInInjectionContext(injector, () => - createBaseQuery( - injectInfiniteQueryFn, - InfiniteQueryObserver as typeof QueryObserver, - ), - ) -} diff --git a/packages/angular-query-experimental/src/inject-is-fetching.ts b/packages/angular-query-experimental/src/inject-is-fetching.ts deleted file mode 100644 index 5517fc29849..00000000000 --- a/packages/angular-query-experimental/src/inject-is-fetching.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { - DestroyRef, - Injector, - NgZone, - assertInInjectionContext, - inject, - signal, -} from '@angular/core' -import { QueryClient, notifyManager } from '@tanstack/query-core' -import type { QueryFilters } from '@tanstack/query-core' -import type { Signal } from '@angular/core' - -export interface InjectIsFetchingOptions { - /** - * The `Injector` in which to create the isFetching signal. - * - * If this is not provided, the current injection context will be used instead (via `inject`). - */ - injector?: Injector -} - -/** - * Injects a signal that tracks the number of queries that your application is loading or fetching in the - * background (useful for app-wide loading indicators). - * - * @param filters - The {@link QueryFilters} to narrow down the matched queries. - * @param options - Additional configuration - * @returns A `Signal` with the number of queries that your application is currently loading or fetching in - * the background. - * - * @example - * ```angular-ts - * @Component({ - * selector: 'posts-fetching-indicator', - * template: ` - * @if (isFetchingPosts()) { - * Refreshing posts... - * } - * `, - * }) - * export class PostsFetchingIndicator { - * // How many queries matching the posts prefix are fetching? - * readonly isFetchingPosts = injectIsFetching({ queryKey: ['posts'] }) - * } - * ``` - * - * @example - * A global loading indicator for any query fetching in the background, not just the ones on screen: - * ```angular-ts - * @Component({ - * selector: 'global-loading-indicator', - * template: ` - * @if (isFetching()) { - *
Queries are fetching in the background...
- * } - * `, - * }) - * export class GlobalLoadingIndicator { - * readonly isFetching = injectIsFetching() - * } - * ``` - */ -export function injectIsFetching( - filters?: QueryFilters, - options?: InjectIsFetchingOptions, -): Signal { - !options?.injector && assertInInjectionContext(injectIsFetching) - const injector = options?.injector ?? inject(Injector) - const destroyRef = injector.get(DestroyRef) - const ngZone = injector.get(NgZone) - const queryClient = injector.get(QueryClient) - - const cache = queryClient.getQueryCache() - // isFetching is the prev value initialized on mount * - let isFetching = queryClient.isFetching(filters) - - const result = signal(isFetching) - - const unsubscribe = ngZone.runOutsideAngular(() => - cache.subscribe( - notifyManager.batchCalls(() => { - const newIsFetching = queryClient.isFetching(filters) - if (isFetching !== newIsFetching) { - // * and update with each change - isFetching = newIsFetching - ngZone.run(() => { - result.set(isFetching) - }) - } - }), - ), - ) - - destroyRef.onDestroy(unsubscribe) - - return result -} diff --git a/packages/angular-query-experimental/src/inject-is-mutating.ts b/packages/angular-query-experimental/src/inject-is-mutating.ts deleted file mode 100644 index 42a41ad0e7a..00000000000 --- a/packages/angular-query-experimental/src/inject-is-mutating.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { - DestroyRef, - Injector, - NgZone, - assertInInjectionContext, - inject, - signal, -} from '@angular/core' -import { QueryClient, notifyManager } from '@tanstack/query-core' -import type { MutationFilters } from '@tanstack/query-core' -import type { Signal } from '@angular/core' - -export interface InjectIsMutatingOptions { - /** - * The `Injector` in which to create the isMutating signal. - * - * If this is not provided, the current injection context will be used instead (via `inject`). - */ - injector?: Injector -} - -/** - * Injects a signal that tracks the number of mutations that your application currently has `pending` - * (useful for app-wide loading indicators). - * - * @param filters - The {@link MutationFilters} to narrow down the matched mutations. - * @param options - Additional configuration - * @returns A `Signal` with the number of mutations that your application currently has `pending`. - * - * @example - * ```angular-ts - * @Component({ - * selector: 'posts-mutating-indicator', - * template: ` - * @if (isMutatingPosts()) { - * Saving posts... - * } - * `, - * }) - * export class PostsMutatingIndicator { - * // How many mutations matching the posts prefix are in progress? - * readonly isMutatingPosts = injectIsMutating({ mutationKey: ['posts'] }) - * } - * ``` - */ -export function injectIsMutating( - filters?: MutationFilters, - options?: InjectIsMutatingOptions, -): Signal { - !options?.injector && assertInInjectionContext(injectIsMutating) - const injector = options?.injector ?? inject(Injector) - const destroyRef = injector.get(DestroyRef) - const ngZone = injector.get(NgZone) - const queryClient = injector.get(QueryClient) - - const cache = queryClient.getMutationCache() - // isMutating is the prev value initialized on mount * - let isMutating = queryClient.isMutating(filters) - - const result = signal(isMutating) - - const unsubscribe = ngZone.runOutsideAngular(() => - cache.subscribe( - notifyManager.batchCalls(() => { - const newIsMutating = queryClient.isMutating(filters) - if (isMutating !== newIsMutating) { - // * and update with each change - isMutating = newIsMutating - ngZone.run(() => { - result.set(isMutating) - }) - } - }), - ), - ) - - destroyRef.onDestroy(unsubscribe) - - return result.asReadonly() -} diff --git a/packages/angular-query-experimental/src/inject-is-restoring.ts b/packages/angular-query-experimental/src/inject-is-restoring.ts deleted file mode 100644 index 901f5e55852..00000000000 --- a/packages/angular-query-experimental/src/inject-is-restoring.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { - InjectionToken, - Injector, - assertInInjectionContext, - inject, - signal, -} from '@angular/core' -import type { Provider, Signal } from '@angular/core' - -/** - * Internal token used to track isRestoring state, accessible in public API through `injectIsRestoring` and set via `provideIsRestoring` - */ -const IS_RESTORING = new InjectionToken('', { - // Default value when not provided - factory: () => signal(false).asReadonly(), -}) - -interface InjectIsRestoringOptions { - /** - * The `Injector` to use to get the isRestoring signal. - * - * If this is not provided, the current injection context will be used instead (via `inject`). - */ - injector?: Injector -} - -/** - * Injects a signal that tracks whether a restore (e.g. from a persisted client, wired up via - * `provideIsRestoring`) is currently in progress. `injectQuery` and friends also check this internally to - * avoid race conditions between the restore and initializing queries. - * @param options - Additional configuration - * @returns A readonly `Signal` — `true` while a restore is in progress, `false` otherwise (the - * default when no `provideIsRestoring` provider is registered). - */ -export function injectIsRestoring(options?: InjectIsRestoringOptions) { - !options?.injector && assertInInjectionContext(injectIsRestoring) - const injector = options?.injector ?? inject(Injector) - return injector.get(IS_RESTORING) -} - -/** - * Registers a provider for the restore state read by `injectIsRestoring`. Wire this up wherever you drive a - * restore yourself — e.g. a persist-client integration — so `injectQuery` and friends can defer subscribing - * to their observer (avoiding a race with the restore) until the restore signal flips back to `false`. - * @param isRestoring - A readonly `Signal` that tracks the restore state. - * @returns A provider for the `isRestoring` signal. - */ -export function provideIsRestoring(isRestoring: Signal): Provider { - return { - provide: IS_RESTORING, - useValue: isRestoring, - } -} diff --git a/packages/angular-query-experimental/src/inject-mutation-state.ts b/packages/angular-query-experimental/src/inject-mutation-state.ts deleted file mode 100644 index 3a1dcf7beee..00000000000 --- a/packages/angular-query-experimental/src/inject-mutation-state.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { - DestroyRef, - Injector, - NgZone, - assertInInjectionContext, - computed, - inject, - signal, -} from '@angular/core' -import { - QueryClient, - notifyManager, - replaceEqualDeep, -} from '@tanstack/query-core' -import type { Signal } from '@angular/core' -import type { - Mutation, - MutationCache, - MutationFilters, - MutationState, -} from '@tanstack/query-core' - -type MutationStateOptions = { - filters?: MutationFilters - select?: (mutation: Mutation) => TResult -} - -function getResult( - mutationCache: MutationCache, - options: MutationStateOptions, -): Array { - return mutationCache - .findAll(options.filters) - .map( - (mutation): TResult => - (options.select ? options.select(mutation) : mutation.state) as TResult, - ) -} - -export interface InjectMutationStateOptions { - /** - * The `Injector` in which to create the mutation state signal. - * - * If this is not provided, the current injection context will be used instead (via `inject`). - */ - injector?: Injector -} - -/** - * Injects a signal that gives you access to all mutations in the `MutationCache`. You can pass `filters` - * ({@link MutationFilters}) to narrow down your mutations, and `select` to transform the mutation state. - * - * @param injectMutationStateFn - A function returning the `filters` to narrow down matched mutations, and an - * optional `select` to transform the mutation state. Similar to `computed` from Angular, this function runs - * in the reactive context, so signals read inside it re-narrow the matched mutations. - * @param options - Additional configuration - * @returns A `Signal` with an Array of whatever `select` returns for each matching mutation. - * - * @example - * Get all variables of all running mutations: - * ```angular-ts - * @Component({ - * selector: 'pending-posts', - * template: `{{ pendingVariables().length }} posts saving...`, - * }) - * export class PendingPosts { - * readonly pendingVariables = injectMutationState(() => ({ - * filters: { status: 'pending' }, - * select: (mutation) => mutation.state.variables, - * })) - * } - * ``` - * - * @example - * Get all data for specific mutations via the `mutationKey`: - * ```angular-ts - * const mutationKey = ['posts'] - * - * @Component({ - * selector: 'posts', - * template: ` - * - * `, - * }) - * export class Posts { - * // Some mutation that we want to get the state for - * readonly createPostMutation = injectMutation(() => ({ - * mutationKey, - * mutationFn: createPosts, - * })) - * - * readonly savedPosts = injectMutationState(() => ({ - * // this mutation key needs to match the mutation key of the given mutation (see above) - * filters: { mutationKey, status: 'success' }, - * select: (mutation) => mutation.state.data, - * })) - * - * createPost() { - * this.createPostMutation.mutate(['New Post']) - * } - * } - * ``` - */ -export function injectMutationState( - injectMutationStateFn: () => MutationStateOptions = () => ({}), - options?: InjectMutationStateOptions, -): Signal> { - !options?.injector && assertInInjectionContext(injectMutationState) - const injector = options?.injector ?? inject(Injector) - const destroyRef = injector.get(DestroyRef) - const ngZone = injector.get(NgZone) - const queryClient = injector.get(QueryClient) - const mutationCache = queryClient.getMutationCache() - - /** - * Computed signal that gets result from mutation cache based on passed options - * First element is the result, second element is the time when the result was set - */ - const resultFromOptionsSignal = computed(() => { - return [ - getResult(mutationCache, injectMutationStateFn()), - performance.now(), - ] as const - }) - - /** - * Signal that contains result set by subscriber - * First element is the result, second element is the time when the result was set - */ - const resultFromSubscriberSignal = signal<[Array, number] | null>( - null, - ) - - /** - * Returns the last result by either subscriber or options - */ - const effectiveResultSignal = computed(() => { - const optionsResult = resultFromOptionsSignal() - const subscriberResult = resultFromSubscriberSignal() - return subscriberResult && subscriberResult[1] > optionsResult[1] - ? subscriberResult[0] - : optionsResult[0] - }) - - const unsubscribe = ngZone.runOutsideAngular(() => - mutationCache.subscribe( - notifyManager.batchCalls(() => { - const [lastResult] = effectiveResultSignal() - const nextResult = replaceEqualDeep( - lastResult, - getResult(mutationCache, injectMutationStateFn()), - ) - if (lastResult !== nextResult) { - ngZone.run(() => { - resultFromSubscriberSignal.set([nextResult, performance.now()]) - }) - } - }), - ), - ) - - destroyRef.onDestroy(unsubscribe) - - return effectiveResultSignal -} diff --git a/packages/angular-query-experimental/src/inject-mutation.ts b/packages/angular-query-experimental/src/inject-mutation.ts deleted file mode 100644 index 6fac7e5e73e..00000000000 --- a/packages/angular-query-experimental/src/inject-mutation.ts +++ /dev/null @@ -1,328 +0,0 @@ -import { - Injector, - NgZone, - assertInInjectionContext, - computed, - effect, - inject, - signal, - untracked, -} from '@angular/core' -import { - MutationObserver, - QueryClient, - noop, - notifyManager, - shouldThrowError, -} from '@tanstack/query-core' -import { signalProxy } from './signal-proxy' -import { PENDING_TASKS } from './pending-tasks-compat' -import type { PendingTaskRef } from './pending-tasks-compat' -import type { DefaultError, MutationObserverResult } from '@tanstack/query-core' -import type { - CreateMutateFunction, - CreateMutationOptions, - CreateMutationResult, -} from './types' - -export interface InjectMutationOptions { - /** - * The `Injector` in which to create the mutation. - * - * If this is not provided, the current injection context will be used instead (via `inject`). - */ - injector?: Injector -} - -/** - * Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. - * `injectMutation` is the function for that. Unlike queries, mutations are not run automatically. - * - * @remarks `mutate`/`mutateAsync` also accept per-call `onSuccess`/`onError`/`onSettled` callbacks as a - * second argument, useful for triggering call-site side effects (e.g. navigation) without coupling them to - * the shared mutation definition. Callbacks defined in `injectMutationFn` fire for every mutation; per-call - * callbacks fire only for the latest call you've made — `mutateAsync` gives you a promise per call instead, - * so you can await `Promise.all`/`Promise.allSettled` over several calls and see each one's outcome. - * @see {@link mutationOptions} to share these options across multiple `injectMutation` call sites, or to look - * the mutation up elsewhere via its `mutationKey` (e.g. with `injectMutationState`). - * @param injectMutationFn - A function that returns mutation options. Similar to `computed` from Angular, - * this function runs in the reactive context, so signals read inside it drive the mutation's options. - * @param options - Additional configuration - * @returns The mutation result. Value fields are exposed as a `Signal` — read `data`/`error` by calling them - * (e.g. `mutation.data()`) — while function fields (`mutate`, `mutateAsync`, `reset`) are called directly, - * unchanged. `isSuccess`/`isError`/`isPending`/`isIdle` are type-guard methods you can call to narrow whether - * `data` is defined. - * - * @example - * ```angular-ts - * @Component({ - * selector: 'todos', - * template: ` - * @if (addMutation.isPending()) { - * Adding todo... - * } @else if (addMutation.isError()) { - *
An error occurred: {{ addMutation.error()?.message }}
- * } - * - * `, - * }) - * export class Todos { - * readonly #queryClient = inject(QueryClient) - * - * readonly addMutation = injectMutation(() => ({ - * mutationFn: addTodo, - * onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), - * })) - * } - * ``` - * - * @example - * Optimistic update via `onMutate`, rolling back on `onError`: - * ```angular-ts - * @Component({ - * selector: 'todos', - * template: ``, - * }) - * export class Todos { - * readonly #queryClient = inject(QueryClient) - * - * readonly addMutation = injectMutation(() => ({ - * mutationFn: addTodo, - * onMutate: async (newTodo) => { - * await this.#queryClient.cancelQueries({ queryKey: ['todos'] }) - * const previousTodos = this.#queryClient.getQueryData>(['todos']) - * - * this.#queryClient.setQueryData>(['todos'], (old) => [ - * ...(old ?? []), - * newTodo, - * ]) - * - * // Passed to `onError` as `onMutateResult` if the mutation fails. - * return { previousTodos } - * }, - * onError: (_err, _newTodo, onMutateResult) => { - * this.#queryClient.setQueryData(['todos'], onMutateResult?.previousTodos) - * }, - * onSettled: () => { - * this.#queryClient.invalidateQueries({ queryKey: ['todos'] }) - * }, - * })) - * } - * ``` - * - * @example - * Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a promise per - * call instead, so you can wait for all of them when they succeed: - * ```angular-ts - * @Component({ - * selector: 'todos', - * template: ` - * - * `, - * }) - * export class Todos { - * readonly #queryClient = inject(QueryClient) - * - * readonly addMutation = injectMutation(() => ({ - * mutationFn: addTodo, - * onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), - * })) - * - * async handleAddAll(todos: Array) { - * try { - * await Promise.all(todos.map((todo) => this.addMutation.mutateAsync(todo))) - * } catch (error) { - * console.error('Failed to add todos:', error) - * } - * } - * } - * ``` - * - * @example - * If some of the mutations above can fail independently of the others, and you want to know which ones did — - * rather than losing that information the moment the first one rejects — swap `Promise.all` for - * `Promise.allSettled`: - * ```angular-ts - * @Component({ - * selector: 'todos', - * template: ` - * - * `, - * }) - * export class Todos { - * readonly #queryClient = inject(QueryClient) - * - * readonly addMutation = injectMutation(() => ({ - * mutationFn: addTodo, - * onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), - * })) - * - * async handleAddAll(todos: Array) { - * const addResults = await Promise.allSettled( - * todos.map((todo) => this.addMutation.mutateAsync(todo)), - * ) - * - * addResults.forEach((addResult, index) => { - * if (addResult.status === 'rejected') { - * console.error(`Failed to add "${todos[index]}":`, addResult.reason) - * } - * }) - * } - * } - * ``` - */ -export function injectMutation< - TData = unknown, - TError = DefaultError, - TVariables = void, - TOnMutateResult = unknown, ->( - injectMutationFn: () => CreateMutationOptions< - TData, - TError, - TVariables, - TOnMutateResult - >, - options?: InjectMutationOptions, -): CreateMutationResult { - !options?.injector && assertInInjectionContext(injectMutation) - const injector = options?.injector ?? inject(Injector) - const ngZone = injector.get(NgZone) - const pendingTasks = injector.get(PENDING_TASKS) - const queryClient = injector.get(QueryClient) - - /** - * computed() is used so signals can be inserted into the options - * making it reactive. Wrapping options in a function ensures embedded expressions - * are preserved and can keep being applied after signal changes - */ - const optionsSignal = computed(injectMutationFn) - - const observerSignal = (() => { - let instance: MutationObserver< - TData, - TError, - TVariables, - TOnMutateResult - > | null = null - - return computed(() => { - return (instance ||= new MutationObserver(queryClient, optionsSignal())) - }) - })() - - const mutateFnSignal = computed< - CreateMutateFunction - >(() => { - const observer = observerSignal() - return ( - ...args: Parameters< - CreateMutateFunction - > - ) => { - observer.mutate(args[0] as TVariables, args[1]).catch(noop) - } - }) - - /** - * Computed signal that gets result from mutation cache based on passed options - */ - const resultFromInitialOptionsSignal = computed(() => { - const observer = observerSignal() - return observer.getCurrentResult() - }) - - /** - * Signal that contains result set by subscriber - */ - const resultFromSubscriberSignal = signal | null>(null) - - effect( - () => { - const observer = observerSignal() - const observerOptions = optionsSignal() - - untracked(() => { - observer.setOptions(observerOptions) - }) - }, - { - injector, - }, - ) - - effect( - (onCleanup) => { - // observer.trackResult is not used as this optimization is not needed for Angular - const observer = observerSignal() - let pendingTaskRef: PendingTaskRef | null = null - - untracked(() => { - const unsubscribe = ngZone.runOutsideAngular(() => - observer.subscribe( - notifyManager.batchCalls((state) => { - ngZone.run(() => { - // Track pending task when mutation is pending - if (state.isPending && !pendingTaskRef) { - pendingTaskRef = pendingTasks.add() - } - - // Clear pending task when mutation is no longer pending - if (!state.isPending && pendingTaskRef) { - pendingTaskRef() - pendingTaskRef = null - } - - if ( - state.isError && - shouldThrowError(observer.options.throwOnError, [state.error]) - ) { - ngZone.onError.emit(state.error) - throw state.error - } - - resultFromSubscriberSignal.set(state) - }) - }), - ), - ) - onCleanup(() => { - // Clean up any pending task on destroy - if (pendingTaskRef) { - pendingTaskRef() - pendingTaskRef = null - } - unsubscribe() - }) - }) - }, - { - injector, - }, - ) - - const resultSignal = computed(() => { - const resultFromSubscriber = resultFromSubscriberSignal() - const resultFromInitialOptions = resultFromInitialOptionsSignal() - - const result = resultFromSubscriber ?? resultFromInitialOptions - - return { - ...result, - mutate: mutateFnSignal(), - mutateAsync: result.mutate, - } - }) - - return signalProxy(resultSignal) as CreateMutationResult< - TData, - TError, - TVariables, - TOnMutateResult - > -} diff --git a/packages/angular-query-experimental/src/inject-queries-experimental/index.ts b/packages/angular-query-experimental/src/inject-queries-experimental/index.ts deleted file mode 100644 index d300d7d2a55..00000000000 --- a/packages/angular-query-experimental/src/inject-queries-experimental/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from '../inject-queries' diff --git a/packages/angular-query-experimental/src/inject-queries.ts b/packages/angular-query-experimental/src/inject-queries.ts deleted file mode 100644 index 47d692716d8..00000000000 --- a/packages/angular-query-experimental/src/inject-queries.ts +++ /dev/null @@ -1,479 +0,0 @@ -import { - QueriesObserver, - QueryClient, - notifyManager, -} from '@tanstack/query-core' -import { - DestroyRef, - Injector, - NgZone, - assertInInjectionContext, - computed, - effect, - inject, - runInInjectionContext, - signal, - untracked, -} from '@angular/core' -import { signalProxy } from './signal-proxy' -import { injectIsRestoring } from './inject-is-restoring' -import type { - DefaultError, - OmitKeyof, - QueriesObserverOptions, - QueriesPlaceholderDataFunction, - QueryFunction, - QueryKey, - QueryObserverOptions, - ThrowOnError, -} from '@tanstack/query-core' -import type { - CreateQueryOptions, - CreateQueryResult, - DefinedCreateQueryResult, -} from './types' -import type { Signal } from '@angular/core' - -// This defines the `CreateQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`. -// `placeholderData` function always gets undefined passed -type QueryObserverOptionsForCreateQueries< - TQueryFnData = unknown, - TError = DefaultError, - TData = TQueryFnData, - TQueryKey extends QueryKey = QueryKey, -> = OmitKeyof< - CreateQueryOptions, - 'placeholderData' -> & { - placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction -} - -// Avoid TS depth-limit error in case of large array literal -type MAXIMUM_DEPTH = 20 - -// Widen the type of the symbol to enable type inference even if skipToken is not immutable. -type SkipTokenForCreateQueries = symbol - -type GetCreateQueryOptionsForCreateQueries = - // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData } - T extends { - queryFnData: infer TQueryFnData - error?: infer TError - data: infer TData - } - ? QueryObserverOptionsForCreateQueries - : T extends { queryFnData: infer TQueryFnData; error?: infer TError } - ? QueryObserverOptionsForCreateQueries - : T extends { data: infer TData; error?: infer TError } - ? QueryObserverOptionsForCreateQueries - : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData] - T extends [infer TQueryFnData, infer TError, infer TData] - ? QueryObserverOptionsForCreateQueries - : T extends [infer TQueryFnData, infer TError] - ? QueryObserverOptionsForCreateQueries - : T extends [infer TQueryFnData] - ? QueryObserverOptionsForCreateQueries - : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided - T extends { - queryFn?: - | QueryFunction - | SkipTokenForCreateQueries - select?: (data: any) => infer TData - throwOnError?: ThrowOnError - } - ? QueryObserverOptionsForCreateQueries< - TQueryFnData, - unknown extends TError ? DefaultError : TError, - unknown extends TData ? TQueryFnData : TData, - TQueryKey - > - : // Fallback - QueryObserverOptionsForCreateQueries - -// A defined initialData setting should return a DefinedCreateQueryResult rather than CreateQueryResult -type GetDefinedOrUndefinedQueryResult = T extends { - initialData?: infer TInitialData -} - ? unknown extends TInitialData - ? CreateQueryResult - : TInitialData extends TData - ? DefinedCreateQueryResult - : TInitialData extends () => infer TInitialDataResult - ? unknown extends TInitialDataResult - ? CreateQueryResult - : TInitialDataResult extends TData - ? DefinedCreateQueryResult - : CreateQueryResult - : CreateQueryResult - : CreateQueryResult - -type GetCreateQueryResult = - // Part 1: responsible for mapping explicit type parameter to function result, if object - T extends { queryFnData: any; error?: infer TError; data: infer TData } - ? GetDefinedOrUndefinedQueryResult - : T extends { queryFnData: infer TQueryFnData; error?: infer TError } - ? GetDefinedOrUndefinedQueryResult - : T extends { data: infer TData; error?: infer TError } - ? GetDefinedOrUndefinedQueryResult - : // Part 2: responsible for mapping explicit type parameter to function result, if tuple - T extends [any, infer TError, infer TData] - ? GetDefinedOrUndefinedQueryResult - : T extends [infer TQueryFnData, infer TError] - ? GetDefinedOrUndefinedQueryResult - : T extends [infer TQueryFnData] - ? GetDefinedOrUndefinedQueryResult - : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided - T extends { - queryFn?: - | QueryFunction - | SkipTokenForCreateQueries - select?: (data: any) => infer TData - throwOnError?: ThrowOnError - } - ? GetDefinedOrUndefinedQueryResult< - T, - unknown extends TData ? TQueryFnData : TData, - unknown extends TError ? DefaultError : TError - > - : // Fallback - CreateQueryResult - -/** - * The `queries` array accepted by `injectQueries`. Recursively unwraps each tuple element so every entry's - * `queryFn`/`select`/`throwOnError` are inferred individually, up to 20 elements — past that, tuple - * recursion falls back to a single homogeneous options type. An opaque array (e.g. `unknown[]`) is returned - * as-is; a non-tuple array of a known element type is mapped to that element type instead, with no such - * limit. - * - * @template T - The type of the `queries` array as written at the call site. - * @template TResults - The internal accumulator that this type builds during recursion. It is not meant to - * be set explicitly. - * @template TDepth - The internal recursion-depth counter, checked against the 20-element limit. It is not - * meant to be set explicitly. - */ -export type QueriesOptions< - T extends Array, - TResults extends Array = [], - TDepth extends ReadonlyArray = [], -> = TDepth['length'] extends MAXIMUM_DEPTH - ? Array - : T extends [] - ? [] - : T extends [infer Head] - ? [...TResults, GetCreateQueryOptionsForCreateQueries] - : T extends [infer Head, ...infer Tails] - ? QueriesOptions< - [...Tails], - [...TResults, GetCreateQueryOptionsForCreateQueries], - [...TDepth, 1] - > - : ReadonlyArray extends T - ? T - : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogeneous type! - // use this to infer the param types in the case of Array.map() argument - T extends Array< - QueryObserverOptionsForCreateQueries< - infer TQueryFnData, - infer TError, - infer TData, - infer TQueryKey - > - > - ? Array< - QueryObserverOptionsForCreateQueries< - TQueryFnData, - TError, - TData, - TQueryKey - > - > - : // Fallback - Array - -/** - * The result type returned by `injectQueries`, when no `combine` is provided. Mirrors {@link QueriesOptions}: - * each tuple element's result type is inferred individually, up to 20 elements — past that, tuple recursion - * falls back to a single homogeneous {@link CreateQueryResult} type. A non-tuple array is mapped per-element - * instead, with no such limit — every entry keeps its individually inferred type regardless of array length. - * - * @template T - The type of the `queries` array, as inferred by {@link QueriesOptions}. - * @template TResults - The internal accumulator that this type builds during recursion. It is not meant to - * be set explicitly. - * @template TDepth - The internal recursion-depth counter, checked against the 20-element limit. It is not - * meant to be set explicitly. - */ -export type QueriesResults< - T extends Array, - TResults extends Array = [], - TDepth extends ReadonlyArray = [], -> = TDepth['length'] extends MAXIMUM_DEPTH - ? Array - : T extends [] - ? [] - : T extends [infer Head] - ? [...TResults, GetCreateQueryResult] - : T extends [infer Head, ...infer Tails] - ? QueriesResults< - [...Tails], - [...TResults, GetCreateQueryResult], - [...TDepth, 1] - > - : { [K in keyof T]: GetCreateQueryResult } - -export interface InjectQueriesOptions< - T extends Array, - TCombinedResult = QueriesResults, -> { - queries: - | readonly [...QueriesOptions] - | readonly [ - ...{ [K in keyof T]: GetCreateQueryOptionsForCreateQueries }, - ] - combine?: (result: QueriesResults) => TCombinedResult -} - -/** - * Injects a signal to fetch a variable number of queries. - * - * The `queries` key accepts an array with query option objects mostly identical to `injectQuery`'s. Having - * the same query key more than once in the array of query objects may cause some data to be shared between - * queries. To avoid this, consider de-duplicating the queries and map the results back to the desired - * structure. - * - * The `combine` option can be used to combine the results of the queries into a single value. The result - * will be structurally shared to be as referentially stable as possible. - * - * @remarks Unlike `injectQuery`, `injectQueries` cannot infer the `data` argument of an _inline_ `select` - * from its sibling `queryFn`. Because `injectQueries` infers the type of the whole `queries` array at once, - * the `select` parameter of a query object written inline cannot be contextually typed from that same - * object's `queryFn`, so it falls back to `unknown` — a - * [known TypeScript limitation](https://github.com/TanStack/query/issues/6556). Annotate the `select` - * parameter explicitly, or define the query with {@link queryOptions}, which resolves its types in a single - * object _before_ it reaches `injectQueries`, to work around this — see the example below. - * @param optionsFn - A function returning the queries' options — an array of query option objects under - * `queries`, and an optional `combine`. Similar to `computed` from Angular, this function runs in the - * reactive context, so signals read inside it (e.g. to build the `queries` array) drive the queries. - * @param injector - The `Injector` in which to create the queries. If this is not provided, the current - * injection context will be used instead (via `inject`). - * @returns A `Signal` with the combined result. Without `combine`, this is an array with all the query - * results, in the same order as the input. When `combine` is provided, this is the value returned by - * `combine` instead. - * - * @example - * ```angular-ts - * @Component({ - * selector: 'posts', - * template: ` - *
    - * @for (query of postQueries(); track $index) { - * @if (query.isPending()) { - *
  • Loading...
  • - * } @else if (query.isError()) { - *
  • Error: {{ query.error()?.message }}
  • - * } @else { - *
  • {{ query.data().title }}
  • - * } - * } - *
- * `, - * }) - * export class Posts { - * readonly ids = signal([1, 2, 3]) - * - * readonly postQueries = injectQueries(() => ({ - * queries: this.ids().map((id) => ({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), - * staleTime: Infinity, - * })), - * })) - * } - * ``` - * - * @example - * Combining results into a single value: - * ```angular-ts - * @Component({ - * selector: 'posts', - * template: ` - * @if (combined().isPending) { - * Loading... - * } @else if (combined().isError) { - * Error loading posts - * } @else { - *
    - * @for (post of combined().data; track post?.id) { - *
  • {{ post?.title }}
  • - * } - *
- * } - * `, - * }) - * export class Posts { - * readonly ids = signal([1, 2, 3]) - * - * readonly combined = injectQueries(() => ({ - * queries: this.ids().map((id) => ({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), - * })), - * combine: (postQueries) => ({ - * data: postQueries.map((query) => query.data), - * isPending: postQueries.some((query) => query.isPending), - * isError: postQueries.some((query) => query.isError), - * }), - * })) - * } - * ``` - * - * @example - * Typing `select` via {@link queryOptions}. Note that spreading a `queryOptions` result and overriding - * `select` inline still falls back to `unknown` — wrap the spread in `queryOptions` again so the override is - * resolved before it reaches `injectQueries`: - * ```angular-ts - * const postOptions = (id: number) => - * queryOptions({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), - * }) - * - * @Component({ - * selector: 'post-title', - * template: `

{{ fixed()[0].data() }}

`, - * }) - * export class PostTitle { - * readonly id = signal(1) - * - * readonly broken = injectQueries(() => ({ - * queries: [ - * { - * ...postOptions(this.id()), - * // ❌ `data` is `unknown` here - * select: (data) => data.title, - * }, - * ], - * })) - * - * readonly fixed = injectQueries(() => ({ - * queries: [ - * queryOptions({ - * ...postOptions(this.id()), - * // ✅ `data` is `Post` - * select: (data) => data.title, - * }), - * ], - * })) - * } - * ``` - */ -export function injectQueries< - T extends Array, - TCombinedResult = QueriesResults, ->( - optionsFn: () => InjectQueriesOptions, - injector?: Injector, -): Signal { - !injector && assertInInjectionContext(injectQueries) - return runInInjectionContext(injector ?? inject(Injector), () => { - const destroyRef = inject(DestroyRef) - const ngZone = inject(NgZone) - const queryClient = inject(QueryClient) - const isRestoring = injectIsRestoring() - - /** - * Signal that has the default options from query client applied - * computed() is used so signals can be inserted into the options - * making it reactive. Wrapping options in a function ensures embedded expressions - * are preserved and can keep being applied after signal changes - */ - const optionsSignal = computed(() => { - return optionsFn() - }) - - const defaultedQueries = computed(() => { - return optionsSignal().queries.map((opts) => { - const defaultedOptions = queryClient.defaultQueryOptions( - opts as QueryObserverOptions, - ) - // Make sure the results are already in fetching state before subscribing or updating options - defaultedOptions._optimisticResults = isRestoring() - ? 'isRestoring' - : 'optimistic' - - return defaultedOptions as QueryObserverOptions - }) - }) - - const observerSignal = (() => { - let instance: QueriesObserver | null = null - - return computed(() => { - return (instance ||= new QueriesObserver( - queryClient, - defaultedQueries(), - optionsSignal() as QueriesObserverOptions, - )) - }) - })() - - const optimisticResultSignal = computed(() => - observerSignal().getOptimisticResult( - defaultedQueries(), - (optionsSignal() as QueriesObserverOptions).combine, - ), - ) - - // Do not notify on updates because of changes in the options because - // these changes should already be reflected in the optimistic result. - effect(() => { - observerSignal().setQueries( - defaultedQueries(), - optionsSignal() as QueriesObserverOptions, - ) - }) - - const optimisticCombinedResultSignal = computed(() => { - const [_optimisticResult, getCombinedResult, trackResult] = - optimisticResultSignal() - return getCombinedResult(trackResult()) - }) - - const resultFromSubscriberSignal = signal(null) - - effect(() => { - const observer = observerSignal() - const [_optimisticResult, getCombinedResult] = optimisticResultSignal() - - untracked(() => { - const unsubscribe = isRestoring() - ? () => undefined - : ngZone.runOutsideAngular(() => - observer.subscribe( - notifyManager.batchCalls((state) => { - resultFromSubscriberSignal.set(getCombinedResult(state)) - }), - ), - ) - - destroyRef.onDestroy(unsubscribe) - }) - }) - - const resultSignal = computed(() => { - const subscriberResult = resultFromSubscriberSignal() - const optimisticResult = optimisticCombinedResultSignal() - return subscriberResult ?? optimisticResult - }) - - return computed(() => { - const result = resultSignal() - const { combine } = optionsSignal() - - return combine - ? result - : (result as QueriesResults).map((query) => - signalProxy(signal(query)), - ) - }) - }) as unknown as Signal -} diff --git a/packages/angular-query-experimental/src/inject-query-client.ts b/packages/angular-query-experimental/src/inject-query-client.ts deleted file mode 100644 index 7cd29e38508..00000000000 --- a/packages/angular-query-experimental/src/inject-query-client.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Injector, inject } from '@angular/core' -import { QueryClient } from '@tanstack/query-core' -import type { InjectOptions } from '@angular/core' - -/** - * Injects a `QueryClient` instance and allows passing a custom injector. - * @param injectOptions - Type of the options argument to inject and optionally a custom injector. - * @returns The `QueryClient` instance. - * @deprecated Use `inject(QueryClient)` instead. - * If you need to get a `QueryClient` from a custom injector, use `injector.get(QueryClient)`. - * - * - * **Example** - * ```ts - * const queryClient = injectQueryClient(); - * ``` - */ -export function injectQueryClient( - injectOptions: InjectOptions & { injector?: Injector } = {}, -) { - return (injectOptions.injector ?? inject(Injector)).get(QueryClient) -} diff --git a/packages/angular-query-experimental/src/pending-tasks-compat.ts b/packages/angular-query-experimental/src/pending-tasks-compat.ts deleted file mode 100644 index e156996993e..00000000000 --- a/packages/angular-query-experimental/src/pending-tasks-compat.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { InjectionToken, inject } from '@angular/core' -import * as ng from '@angular/core' -import { noop } from '@tanstack/query-core' - -type PendingTasksCompat = { add: () => PendingTaskRef } - -export type PendingTaskRef = () => void - -export const PENDING_TASKS = new InjectionToken( - 'PENDING_TASKS', - { - factory: (): PendingTasksCompat => { - // Access via Reflect so bundlers stay quiet when the token is absent (Angular < 19). - const token = Reflect.get(ng, 'PendingTasks') as unknown as - | Parameters[0] - | undefined - - const svc: PendingTasksCompat | null = token - ? (inject(token, { optional: true }) as PendingTasksCompat | null) - : null - - // Without PendingTasks we fall back to a stable no-op shim. - return { - add: svc ? () => svc.add() : () => noop, - } - }, - }, -) diff --git a/packages/angular-query-experimental/src/providers.ts b/packages/angular-query-experimental/src/providers.ts deleted file mode 100644 index 9f52c11690f..00000000000 --- a/packages/angular-query-experimental/src/providers.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { DestroyRef, InjectionToken, inject } from '@angular/core' -import { QueryClient } from '@tanstack/query-core' -import type { Provider } from '@angular/core' - -/** - * Usually {@link provideTanStackQuery} is used once to set up TanStack Query and the - * [`QueryClient`](https://tanstack.com/query/latest/docs/reference/QueryClient) for the entire application — - * it calls `provideQueryClient` internally. Use `provideQueryClient` directly to provide a different - * `QueryClient` instance for part of the application, or for unit testing. - * @param queryClient - A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`. - * @returns A provider object that can be used to provide the `QueryClient` instance. - * - * @example - * Providing a test-only `QueryClient` in a component test, without wiring up `provideTanStackQuery`'s other - * defaults: - * ```ts - * TestBed.configureTestingModule({ - * providers: [provideQueryClient(new QueryClient())], - * }) - * ``` - */ -export function provideQueryClient( - queryClient: QueryClient | InjectionToken, -): Provider { - return { - provide: QueryClient, - useFactory: () => { - const client = - queryClient instanceof InjectionToken - ? inject(queryClient) - : queryClient - // Unmount the query client on injector destroy - inject(DestroyRef).onDestroy(() => client.unmount()) - client.mount() - return client - }, - } -} - -/** - * Sets up providers necessary to enable TanStack Query functionality for Angular applications. Allows - * configuring a `QueryClient` and optional features such as developer tools. - * - * @see https://tanstack.com/query/v5/docs/framework/angular/quick-start - * @see {@link withDevtools} - * @param queryClient - A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`. - * @param features - Optional features to configure additional Query functionality. - * @returns A set of providers to set up TanStack Query. - * - * @example - * ```ts - * import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query-experimental' - * - * bootstrapApplication(AppComponent, { - * providers: [provideTanStackQuery(new QueryClient())], - * }) - * ``` - * - * @example - * The same, in an `NgModule`-based application: - * ```ts - * import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query-experimental' - * - * @NgModule({ - * declarations: [AppComponent], - * imports: [BrowserModule], - * providers: [provideTanStackQuery(new QueryClient())], - * bootstrap: [AppComponent], - * }) - * export class AppModule {} - * ``` - * - * @example - * Enabling optional developer tools by adding `withDevtools` — by default, the tools are then loaded when - * your app is in development mode: - * ```ts - * import { - * provideTanStackQuery, - * withDevtools, - * QueryClient, - * } from '@tanstack/angular-query-experimental' - * - * bootstrapApplication(AppComponent, { - * providers: [provideTanStackQuery(new QueryClient(), withDevtools())], - * }) - * ``` - * - * @example - * Using an `InjectionToken` for the `QueryClient` — an advanced optimization that lets TanStack Query be - * absent from the main application bundle, useful for including it on lazy-loaded routes only while still - * sharing a `QueryClient`. This is a small optimization; for most applications it's preferable to provide - * the `QueryClient` in the main application config, as in the examples above: - * ```ts - * export const MY_QUERY_CLIENT = new InjectionToken('', { - * factory: () => new QueryClient(), - * }) - * - * // In a lazy loaded route or lazy loaded component's providers array: - * providers: [provideTanStackQuery(MY_QUERY_CLIENT)] - * ``` - */ -export function provideTanStackQuery( - queryClient: QueryClient | InjectionToken, - ...features: Array -): Array { - return [ - provideQueryClient(queryClient), - features.map((feature) => feature.ɵproviders), - ] -} - -/** - * Sets up providers necessary to enable TanStack Query functionality for Angular applications. - * - * Allows configuring a `QueryClient`. - * @see https://tanstack.com/query/v5/docs/framework/angular/quick-start - * @param queryClient - A `QueryClient` instance. - * @returns A set of providers to set up TanStack Query. - * @deprecated Use `provideTanStackQuery` instead. - */ -export function provideAngularQuery(queryClient: QueryClient): Array { - return provideTanStackQuery(queryClient) -} - -const queryFeatures = ['Devtools', 'PersistQueryClient'] as const - -type QueryFeatureKind = (typeof queryFeatures)[number] - -/** - * Helper type to represent a Query feature. - */ -export interface QueryFeature { - ɵkind: TFeatureKind - ɵproviders: Array -} - -/** - * Helper function to create an object that represents a Query feature. - * @param kind - The kind of feature, e.g. `'Devtools'`. - * @param providers - The Angular providers this feature contributes to `provideTanStackQuery`. - * @returns A Query feature. - */ -export function queryFeature( - kind: TFeatureKind, - providers: Array, -): QueryFeature { - return { ɵkind: kind, ɵproviders: providers } -} - -/** - * A type alias that represents a feature which enables developer tools. - * The type is used to describe the return value of the `withDevtools` function. - * @see {@link withDevtools} - */ -export type DevtoolsFeature = QueryFeature<'Devtools'> - -/** - * A type alias that represents a feature which enables persistence. - * The type is used to describe the return value of the `withPersistQueryClient` function. - */ -export type PersistQueryClientFeature = QueryFeature<'PersistQueryClient'> - -/** - * A type alias that represents all Query features available for use with `provideTanStackQuery`. - * Features can be enabled by adding special functions to the `provideTanStackQuery` call. - * See documentation for each symbol to find corresponding function name. See also `provideTanStackQuery` - * documentation on how to use those functions. - * @see {@link provideTanStackQuery} - */ -export type QueryFeatures = DevtoolsFeature | PersistQueryClientFeature diff --git a/packages/angular-query-experimental/src/signal-proxy.ts b/packages/angular-query-experimental/src/signal-proxy.ts deleted file mode 100644 index e2a9de345f6..00000000000 --- a/packages/angular-query-experimental/src/signal-proxy.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { computed, untracked } from '@angular/core' -import type { Signal } from '@angular/core' - -export type MapToSignals = { - [K in keyof T]: T[K] extends Function ? T[K] : Signal -} - -/** - * Exposes fields of an object passed via an Angular `Signal` as `Computed` signals. - * Functions on the object are passed through as-is. - * @param inputSignal - `Signal` that must return an object. - * @returns A proxy object with the same fields as the input object, but with each field wrapped in a `Computed` signal. - */ -export function signalProxy>( - inputSignal: Signal, -) { - const internalState = {} as MapToSignals - - return new Proxy>(internalState, { - get(target, prop) { - // first check if we have it in our internal state and return it - const computedField = target[prop] - if (computedField) return computedField - - // then, check if it's a function on the resultState and return it - const targetField = untracked(inputSignal)[prop] - if (typeof targetField === 'function') return targetField - - // finally, create a computed field, store it and return it - // @ts-expect-error - return (target[prop] = computed(() => inputSignal()[prop])) - }, - has(_, prop) { - return !!untracked(inputSignal)[prop] - }, - ownKeys() { - return Reflect.ownKeys(untracked(inputSignal)) - }, - getOwnPropertyDescriptor() { - return { - enumerable: true, - configurable: true, - } - }, - }) -} diff --git a/packages/angular-query-persist-client/README.md b/packages/angular-query-persist-client/README.md new file mode 100644 index 00000000000..08526b55a67 --- /dev/null +++ b/packages/angular-query-persist-client/README.md @@ -0,0 +1,33 @@ +# @tanstack/angular-query-persist-client + +Persistence integration for `@tanstack/angular-query`. + +## Installation + +```sh +pnpm add @tanstack/angular-query-persist-client @tanstack/query-persist-client-core +``` + +## Usage + +```ts +import { QueryClient, provideTanStackQuery } from '@tanstack/angular-query' +import { withPersistQueryClient } from '@tanstack/angular-query-persist-client' + +export const appConfig: ApplicationConfig = { + providers: [ + provideTanStackQuery( + () => new QueryClient(), + withPersistQueryClient(() => ({ + persistOptions: { + persister: createAsyncStoragePersister({ storage: localStorage }), + }, + })), + ), + ], +} +``` + +The factory runs only in the browser and inside an Angular injection context. +This makes it safe to access browser-only storage and inject application +services without sharing persistence state between SSR requests. diff --git a/packages/angular-query-persist-client/package.json b/packages/angular-query-persist-client/package.json index a05734d867f..4acb5fa11fc 100644 --- a/packages/angular-query-persist-client/package.json +++ b/packages/angular-query-persist-client/package.json @@ -1,7 +1,6 @@ { "name": "@tanstack/angular-query-persist-client", - "private": true, - "version": "5.103.2", + "version": "4.0.0", "description": "Angular bindings to work with persisters in TanStack/angular-query", "author": "Omer Gronich", "license": "MIT", @@ -20,12 +19,13 @@ "compile": "tsc --project tsconfig.json", "test:eslint": "eslint --concurrency=auto ./src", "test:types": "npm-run-all --serial test:types:*", - "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts56 --tsBuildInfoFile .cache/test-types/ts56.tsbuildinfo", - "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts57 --tsBuildInfoFile .cache/test-types/ts57.tsbuildinfo", - "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts58 --tsBuildInfoFile .cache/test-types/ts58.tsbuildinfo", - "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts59 --tsBuildInfoFile .cache/test-types/ts59.tsbuildinfo", - "test:types:tscurrent": "tsc --project tsconfig.json --outDir .cache/test-types/tscurrent --tsBuildInfoFile .cache/test-types/tscurrent.tsbuildinfo", - "test:types:ts70": "node ../../node_modules/typescript70/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts70 --tsBuildInfoFile .cache/test-types/ts70.tsbuildinfo", + "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js --build", + "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js --build", + "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --build", + "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js --build", + "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js --build", + "test:types:tscurrent": "tsc --build", + "test:types:ts60": "node ../../node_modules/typescript60/lib/tsc.js --build", "test:lib": "vitest", "test:lib:dev": "pnpm run test:lib --watch", "test:build": "publint --strict && attw --pack", @@ -54,21 +54,23 @@ "@tanstack/query-persist-client-core": "workspace:*" }, "devDependencies": { - "@angular/animations": "^20.0.0", - "@angular/common": "^20.0.0", - "@angular/compiler": "^20.0.0", - "@angular/core": "^20.0.0", - "@angular/platform-browser": "^20.0.0", - "@tanstack/angular-query-experimental": "workspace:*", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@angular/router": "^22.0.0", + "@tanstack/angular-query": "workspace:*", "@tanstack/query-test-utils": "workspace:*", - "@testing-library/angular": "^18.0.0", + "@testing-library/angular": "^18.1.1", "@testing-library/dom": "^10.4.0", "eslint-plugin-jsdoc": "^50.5.0", - "npm-run-all2": "^5.0.0" + "npm-run-all2": "^5.0.0", + "typescript": "5.9.3", + "zone.js": "^0.16.0" }, "peerDependencies": { - "@angular/common": ">=16.0.0", - "@angular/core": ">=16.0.0", - "@tanstack/angular-query-experimental": "workspace:^" + "@angular/common": ">=22.0.0", + "@angular/core": ">=22.0.0", + "@tanstack/angular-query": "workspace:^" } } diff --git a/packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts b/packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts index 7a5883120a6..d46bfc1ee1e 100644 --- a/packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts +++ b/packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts @@ -1,24 +1,41 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { QueryClient, + injectIsRestoring, + injectQueries, injectQuery, noop, provideTanStackQuery, -} from '@tanstack/angular-query-experimental' +} from '@tanstack/angular-query' import { persistQueryClientSave } from '@tanstack/query-persist-client-core' import { Component, + EnvironmentInjector, + InjectionToken, + PLATFORM_ID, + createEnvironmentInjector, effect, + inject, provideZonelessChangeDetection, } from '@angular/core' +import { TestBed } from '@angular/core/testing' import { render } from '@testing-library/angular' import { queryKey, sleep } from '@tanstack/query-test-utils' +import * as persistClientCore from '@tanstack/query-persist-client-core' import { withPersistQueryClient } from '../with-persist-query-client' import type { PersistedClient, Persister, } from '@tanstack/query-persist-client-core' +beforeEach(() => { + vi.useFakeTimers() +}) + +afterEach(() => { + vi.useRealTimers() +}) + const createMockPersister = (): Persister => { let storedState: PersistedClient | undefined @@ -55,15 +72,7 @@ const createMockErrorPersister = ( } describe('withPersistQueryClient', () => { - beforeEach(() => { - vi.useFakeTimers() - }) - - afterEach(() => { - vi.useRealTimers() - }) - - it('should restore cache from persister', async () => { + it('restores cache from persister', async () => { const key = queryKey() const states: Array<{ status: string @@ -100,24 +109,21 @@ describe('withPersistQueryClient', () => { queryKey: key, queryFn: () => sleep(10).then(() => 'fetched'), })) - - constructor() { - effect(() => { - states.push({ - status: this.state.status(), - fetchStatus: this.state.fetchStatus(), - data: this.state.data(), - }) + _ = effect(() => { + states.push({ + status: this.state.status(), + fetchStatus: this.state.fetchStatus(), + data: this.state.data(), }) - } + }) } const rendered = await render(Page, { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - queryClient, - withPersistQueryClient({ persistOptions: { persister } }), + () => queryClient, + withPersistQueryClient(() => ({ persistOptions: { persister } })), ), ], }) @@ -152,9 +158,115 @@ describe('withPersistQueryClient', () => { }) }) - it.todo( - '(Once injectQueries is functional) verify that injectQueries transitions to an idle state', - ) + it('restores cache for injectQueries and keeps it idle while restoring', async () => { + const key1 = queryKey() + const key2 = queryKey() + const states: Array< + Array<{ + status: string + fetchStatus: string + data: string | undefined + }> + > = [] + + const queryClient = new QueryClient() + void queryClient.query({ + queryKey: key1, + queryFn: () => sleep(10).then(() => 'hydrated-1'), + }).catch(noop) + void queryClient.query({ + queryKey: key2, + queryFn: () => sleep(10).then(() => 'hydrated-2'), + }).catch(noop) + await vi.advanceTimersByTimeAsync(10) + + const persister = createMockPersister() + persistQueryClientSave({ queryClient, persister }) + await vi.advanceTimersByTimeAsync(0) + queryClient.clear() + + @Component({ + template: ` +
+

{{ formattedData() }}

+

fetchStatus: {{ formattedFetchStatus() }}

+
+ `, + }) + class Page { + state = injectQueries(() => ({ + queries: [ + { + queryKey: key1, + queryFn: () => sleep(10).then(() => 'fetched-1'), + }, + { + queryKey: key2, + queryFn: () => sleep(10).then(() => 'fetched-2'), + }, + ], + })) + + _ = effect(() => { + states.push( + this.state().map((query) => ({ + status: query.status(), + fetchStatus: query.fetchStatus(), + data: query.data(), + })), + ) + }) + + formattedData() { + return this.state() + .map((query) => query.data() ?? 'null') + .join(',') + } + + formattedFetchStatus() { + return this.state() + .map((query) => query.fetchStatus()) + .join(',') + } + } + + const rendered = await render(Page, { + providers: [ + provideZonelessChangeDetection(), + provideTanStackQuery( + () => queryClient, + withPersistQueryClient(() => ({ persistOptions: { persister } })), + ), + ], + }) + + expect(rendered.getByText('fetchStatus: idle,idle')).toBeInTheDocument() + + await vi.advanceTimersByTimeAsync(10) + rendered.fixture.detectChanges() + expect(rendered.getByText('hydrated-1,hydrated-2')).toBeInTheDocument() + expect( + rendered.getByText('fetchStatus: fetching,fetching'), + ).toBeInTheDocument() + + await vi.advanceTimersByTimeAsync(11) + rendered.fixture.detectChanges() + expect(rendered.getByText('fetched-1,fetched-2')).toBeInTheDocument() + expect(rendered.getByText('fetchStatus: idle,idle')).toBeInTheDocument() + + expect(states[0]).toMatchObject([ + { status: 'pending', fetchStatus: 'idle', data: undefined }, + { status: 'pending', fetchStatus: 'idle', data: undefined }, + ]) + expect(states).toContainEqual([ + { status: 'success', fetchStatus: 'fetching', data: 'hydrated-1' }, + { status: 'success', fetchStatus: 'fetching', data: 'hydrated-2' }, + ]) + expect(states[states.length - 1]).toMatchObject([ + { status: 'success', fetchStatus: 'idle', data: 'fetched-1' }, + { status: 'success', fetchStatus: 'idle', data: 'fetched-2' }, + ]) + }) it('should show initialData while restoring', async () => { const key = queryKey() @@ -197,24 +309,21 @@ describe('withPersistQueryClient', () => { // otherwise initialData would be newer and takes precedence initialDataUpdatedAt: 1, })) - - constructor() { - effect(() => { - states.push({ - status: this.state.status(), - fetchStatus: this.state.fetchStatus(), - data: this.state.data(), - }) + _ = effect(() => { + states.push({ + status: this.state.status(), + fetchStatus: this.state.fetchStatus(), + data: this.state.data(), }) - } + }) } const rendered = await render(Page, { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - queryClient, - withPersistQueryClient({ persistOptions: { persister } }), + () => queryClient, + withPersistQueryClient(() => ({ persistOptions: { persister } })), ), ], }) @@ -293,24 +402,21 @@ describe('withPersistQueryClient', () => { }), staleTime: Infinity, })) - - constructor() { - effect(() => { - states.push({ - status: this.state.status(), - fetchStatus: this.state.fetchStatus(), - data: this.state.data(), - }) + _ = effect(() => { + states.push({ + status: this.state.status(), + fetchStatus: this.state.fetchStatus(), + data: this.state.data(), }) - } + }) } const rendered = await render(Page, { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - queryClient, - withPersistQueryClient({ persistOptions: { persister } }), + () => queryClient, + withPersistQueryClient(() => ({ persistOptions: { persister } })), ), ], }) @@ -375,11 +481,11 @@ describe('withPersistQueryClient', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - queryClient, - withPersistQueryClient({ + () => queryClient, + withPersistQueryClient(() => ({ persistOptions: { persister }, onSuccess, - }), + })), ), ], }) @@ -395,6 +501,75 @@ describe('withPersistQueryClient', () => { expect(rendered.getByText('fetched')).toBeInTheDocument() }) + it('should await onSuccess before refetching or subscribing', async () => { + const key = queryKey() + const queryClient = new QueryClient() + void queryClient.query({ + queryKey: key, + queryFn: () => sleep(10).then(() => 'hydrated'), + }).catch(noop) + await vi.advanceTimersByTimeAsync(10) + + const persister = createMockPersister() + persistQueryClientSave({ queryClient, persister }) + await vi.advanceTimersByTimeAsync(0) + + queryClient.clear() + + const fetchSpy = vi.fn(() => sleep(10).then(() => 'fetched')) + const onSuccess = vi.fn(async () => { + await sleep(20) + }) + + @Component({ + template: ` +
+

{{ state.data() ?? 'null' }}

+

fetchStatus: {{ state.fetchStatus() }}

+
+ `, + }) + class Page { + state = injectQuery(() => ({ + queryKey: key, + queryFn: fetchSpy, + })) + } + + const rendered = await render(Page, { + providers: [ + provideZonelessChangeDetection(), + provideTanStackQuery( + () => queryClient, + withPersistQueryClient(() => ({ + persistOptions: { persister }, + onSuccess, + })), + ), + ], + }) + + await vi.advanceTimersByTimeAsync(10) + rendered.fixture.detectChanges() + expect(onSuccess).toHaveBeenCalledTimes(1) + expect(fetchSpy).toHaveBeenCalledTimes(0) + expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument() + + await vi.advanceTimersByTimeAsync(19) + rendered.fixture.detectChanges() + expect(fetchSpy).toHaveBeenCalledTimes(0) + + await vi.advanceTimersByTimeAsync(1) + rendered.fixture.detectChanges() + expect(fetchSpy).toHaveBeenCalledTimes(1) + expect(rendered.getByText('hydrated')).toBeInTheDocument() + expect(rendered.getByText('fetchStatus: fetching')).toBeInTheDocument() + + await vi.advanceTimersByTimeAsync(11) + rendered.fixture.detectChanges() + expect(rendered.getByText('fetched')).toBeInTheDocument() + }) + it('should remove cache after non-successful restoring', async () => { const key = queryKey() const onErrorMock = vi @@ -425,12 +600,12 @@ describe('withPersistQueryClient', () => { providers: [ provideZonelessChangeDetection(), provideTanStackQuery( - queryClient, - withPersistQueryClient({ + () => queryClient, + withPersistQueryClient(() => ({ persistOptions: { persister }, onSuccess, onError, - }), + })), ), ], }) @@ -449,4 +624,252 @@ describe('withPersistQueryClient', () => { expect(onErrorMock).toHaveBeenNthCalledWith(1, error) onErrorMock.mockRestore() }) + + it('should await onError before starting queries after restore failure', async () => { + const key = queryKey() + const onErrorMock = vi + .spyOn(console, 'error') + .mockImplementation(() => undefined) + const queryClient = new QueryClient() + const removeClient = vi.fn() + const [, persister] = createMockErrorPersister(removeClient) + const fetchSpy = vi.fn(() => sleep(10).then(() => 'fetched')) + const onError = vi.fn(async () => { + await sleep(20) + }) + + @Component({ + template: ` +
+

{{ state.data() ?? 'null' }}

+

fetchStatus: {{ state.fetchStatus() }}

+
+ `, + }) + class Page { + state = injectQuery(() => ({ + queryKey: key, + queryFn: fetchSpy, + })) + } + + const rendered = await render(Page, { + providers: [ + provideZonelessChangeDetection(), + provideTanStackQuery( + () => queryClient, + withPersistQueryClient(() => ({ + persistOptions: { persister }, + onError, + })), + ), + ], + }) + + await vi.advanceTimersByTimeAsync(10) + rendered.fixture.detectChanges() + expect(onError).toHaveBeenCalledTimes(1) + expect(fetchSpy).toHaveBeenCalledTimes(0) + expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument() + + await vi.advanceTimersByTimeAsync(19) + rendered.fixture.detectChanges() + expect(fetchSpy).toHaveBeenCalledTimes(0) + + await vi.advanceTimersByTimeAsync(1) + rendered.fixture.detectChanges() + expect(fetchSpy).toHaveBeenCalledTimes(1) + expect(rendered.getByText('fetchStatus: fetching')).toBeInTheDocument() + + await vi.advanceTimersByTimeAsync(11) + rendered.fixture.detectChanges() + expect(rendered.getByText('fetched')).toBeInTheDocument() + + onErrorMock.mockRestore() + }) + + it('factory form can inject a token and restores cache', async () => { + const key = queryKey() + const holder = { persister: createMockPersister() } + const HOLDER = new InjectionToken<{ persister: Persister }>( + 'persist-test-holder', + ) + + const queryClient = new QueryClient() + void queryClient.query({ + queryKey: key, + queryFn: () => sleep(10).then(() => 'hydrated'), + }).catch(noop) + await vi.advanceTimersByTimeAsync(10) + + persistQueryClientSave({ queryClient, persister: holder.persister }) + await vi.advanceTimersByTimeAsync(0) + + queryClient.clear() + + @Component({ + template: ` +
+

{{ state.data() }}

+
+ `, + }) + class Page { + state = injectQuery(() => ({ + queryKey: key, + queryFn: () => sleep(10).then(() => 'fetched'), + })) + } + + const rendered = await render(Page, { + providers: [ + provideZonelessChangeDetection(), + { provide: HOLDER, useValue: holder }, + provideTanStackQuery( + () => queryClient, + withPersistQueryClient(() => ({ + persistOptions: { persister: inject(HOLDER).persister }, + })), + ), + ], + }) + + await vi.advanceTimersByTimeAsync(10) + rendered.fixture.detectChanges() + expect(rendered.getByText('hydrated')).toBeInTheDocument() + }) + + it('factory callback runs only in browser mode', async () => { + const factory = vi.fn(() => ({ + persistOptions: { + persister: createMockPersister(), + }, + })) + + @Component({ + template: `{{ isRestoring() }}`, + }) + class Page { + isRestoring = injectIsRestoring() + } + + const rendered = await render(Page, { + providers: [ + provideZonelessChangeDetection(), + { provide: PLATFORM_ID, useValue: 'server' }, + provideTanStackQuery( + () => new QueryClient(), + withPersistQueryClient(factory), + ), + ], + }) + + rendered.fixture.detectChanges() + + expect(factory).not.toHaveBeenCalled() + expect(rendered.fixture.nativeElement.textContent.trim()).toBe('false') + }) + + it('cleanup subscription runs on injector destroy', async () => { + const key = queryKey() + const queryClient = new QueryClient() + const persister = createMockPersister() + const cleanup = vi.fn() + const subscribeSpy = vi + .spyOn(persistClientCore, 'persistQueryClientSubscribe') + .mockReturnValue(cleanup) + + void queryClient.query({ + queryKey: key, + queryFn: () => sleep(10).then(() => 'hydrated'), + }).catch(noop) + await vi.advanceTimersByTimeAsync(10) + persistQueryClientSave({ queryClient, persister }) + await vi.advanceTimersByTimeAsync(0) + queryClient.clear() + TestBed.configureTestingModule({ + providers: [provideZonelessChangeDetection()], + }) + + const injector = createEnvironmentInjector( + [ + provideTanStackQuery( + () => queryClient, + withPersistQueryClient(() => ({ persistOptions: { persister } })), + ), + ], + TestBed.inject(EnvironmentInjector), + ) + + await vi.advanceTimersByTimeAsync(10) + injector.destroy() + + expect(subscribeSpy).toHaveBeenCalledTimes(1) + expect(cleanup).toHaveBeenCalledTimes(1) + }) + + it('does not subscribe when the injector is destroyed during restore', async () => { + const subscribeSpy = vi.spyOn( + persistClientCore, + 'persistQueryClientSubscribe', + ) + + TestBed.configureTestingModule({ + providers: [provideZonelessChangeDetection()], + }) + + const injector = createEnvironmentInjector( + [ + provideTanStackQuery( + () => new QueryClient(), + withPersistQueryClient(() => ({ + persistOptions: { persister: createMockPersister() }, + })), + ), + ], + TestBed.inject(EnvironmentInjector), + ) + + injector.destroy() + await vi.advanceTimersByTimeAsync(10) + + expect(subscribeSpy).not.toHaveBeenCalled() + }) + it('keeps restoration state independent when a provider configuration is reused', async () => { + TestBed.configureTestingModule({ + providers: [provideZonelessChangeDetection()], + }) + const resolutions: Array<(value: undefined) => void> = [] + const providers = provideTanStackQuery( + () => new QueryClient(), + withPersistQueryClient(() => ({ + persistOptions: { + persister: { + restoreClient: () => + new Promise((resolve) => resolutions.push(resolve)), + persistClient: () => {}, + removeClient: () => {}, + }, + }, + })), + ) + const parent = TestBed.inject(EnvironmentInjector) + const first = createEnvironmentInjector([providers], parent) + const second = createEnvironmentInjector([providers], parent) + const firstState = first.runInContext(() => injectIsRestoring()) + const secondState = second.runInContext(() => injectIsRestoring()) + expect(firstState).not.toBe(secondState) + expect(firstState()).toBe(true) + expect(secondState()).toBe(true) + resolutions[0]!(undefined) + await vi.advanceTimersByTimeAsync(0) + expect(firstState()).toBe(false) + expect(secondState()).toBe(true) + first.destroy() + expect(secondState()).toBe(true) + resolutions[1]!(undefined) + await vi.advanceTimersByTimeAsync(0) + expect(secondState()).toBe(false) + second.destroy() + }) }) diff --git a/packages/angular-query-persist-client/src/with-persist-query-client.ts b/packages/angular-query-persist-client/src/with-persist-query-client.ts index 43f562450a1..f2169e48ed4 100644 --- a/packages/angular-query-persist-client/src/with-persist-query-client.ts +++ b/packages/angular-query-persist-client/src/with-persist-query-client.ts @@ -1,88 +1,84 @@ -import { - QueryClient, - provideIsRestoring, - queryFeature, -} from '@tanstack/angular-query-experimental' +import { QueryClient } from '@tanstack/angular-query' import { DestroyRef, - ENVIRONMENT_INITIALIZER, + InjectionToken, PLATFORM_ID, inject, + makeEnvironmentProviders, + provideEnvironmentInitializer, signal, } from '@angular/core' +import { + provideIsRestoring, + queryFeature, +} from '@tanstack/angular-query/internal' import { isPlatformBrowser } from '@angular/common' import { persistQueryClientRestore, persistQueryClientSubscribe, } from '@tanstack/query-persist-client-core' -import type { PersistQueryClientOptions as PersistQueryClientOptionsCore } from '@tanstack/query-persist-client-core' -import type { PersistQueryClientFeature } from '@tanstack/angular-query-experimental' +import type { WritableSignal } from '@angular/core' +import type { QueryFeature } from '@tanstack/angular-query' +import type { WithPersistQueryClientFn } from './with-persist-query-client.types' -type PersistQueryClientOptions = { - persistOptions: Omit - onSuccess?: () => Promise | unknown - onError?: () => Promise | unknown -} +const RESTORING_STATE = new InjectionToken>( + 'Query restoration state', +) + +export type { + PersistQueryClientUserOptions, + WithPersistQueryClientFn, +} from './with-persist-query-client.types' /** - * Enables persistence. - * - * **Example** + * Enables persistence. The options factory runs once per injector, only in the + * browser, in an Angular injection context. It can call `inject()` and use + * browser APIs such as `localStorage`. * * ```ts - * const localStoragePersister = createAsyncStoragePersister({ - * storage: window.localStorage, - * }) - * - * export const appConfig: ApplicationConfig = { - * providers: [ - * provideTanStackQuery( - * new QueryClient(), - * withPersistQueryClient({ - * persistOptions: { - * persister: localStoragePersister, - * }, - * onSuccess: () => console.log('Restoration completed successfully.'), - * }) - * ), - * ], - * }; + * withPersistQueryClient(() => ({ + * persistOptions: { + * persister: createAsyncStoragePersister({ storage: localStorage }), + * }, + * })) * ``` - * @param persistQueryClientOptions - persistence options and optional onSuccess and onError callbacks which get called when the restoration process is complete. + * + * @param optionsFactory - Creates the persistence options in the browser. * @returns A set of providers for use with `provideTanStackQuery`. * @public */ export function withPersistQueryClient( - persistQueryClientOptions: PersistQueryClientOptions, -): PersistQueryClientFeature { - const isRestoring = signal(true) - const providers = [ - provideIsRestoring(isRestoring.asReadonly()), - { - // Do not use provideEnvironmentInitializer while Angular < v19 is supported - provide: ENVIRONMENT_INITIALIZER, - multi: true, - useValue: () => { - if (!isPlatformBrowser(inject(PLATFORM_ID))) return + optionsFactory: WithPersistQueryClientFn, +): QueryFeature { + return queryFeature( + makeEnvironmentProviders([ + { provide: RESTORING_STATE, useFactory: () => signal(true) }, + provideIsRestoring(() => inject(RESTORING_STATE).asReadonly()), + provideEnvironmentInitializer(() => { + const isRestoring = inject(RESTORING_STATE) + if (!isPlatformBrowser(inject(PLATFORM_ID))) { + isRestoring.set(false) + return + } const destroyRef = inject(DestroyRef) const queryClient = inject(QueryClient) - const { onSuccess, onError, persistOptions } = persistQueryClientOptions + const { onSuccess, onError, persistOptions } = optionsFactory() const options = { queryClient, ...persistOptions } - persistQueryClientRestore(options) + void persistQueryClientRestore(options) .then(() => { - onSuccess?.() + return onSuccess?.() }) .catch(() => { - onError?.() + return onError?.() }) .finally(() => { + if (destroyRef.destroyed) return isRestoring.set(false) const cleanup = persistQueryClientSubscribe(options) destroyRef.onDestroy(cleanup) }) - }, - }, - ] - return queryFeature('PersistQueryClient', providers) + }), + ]), + ) } diff --git a/packages/angular-query-persist-client/src/with-persist-query-client.types.ts b/packages/angular-query-persist-client/src/with-persist-query-client.types.ts new file mode 100644 index 00000000000..56c1b06e12c --- /dev/null +++ b/packages/angular-query-persist-client/src/with-persist-query-client.types.ts @@ -0,0 +1,15 @@ +import type { PersistQueryClientOptions as PersistQueryClientOptionsCore } from '@tanstack/query-persist-client-core' + +export type PersistQueryClientUserOptions = { + persistOptions: Omit + /** Called after restoration succeeds. A returned promise is awaited. */ + onSuccess?: () => unknown + /** Called if restoration fails. A returned promise is awaited. */ + onError?: () => unknown +} + +/** + * Returns persistence options. The function runs once in an Angular injection + * context in the browser, so it can call `inject()` and touch browser APIs. + */ +export type WithPersistQueryClientFn = () => PersistQueryClientUserOptions diff --git a/packages/angular-query-persist-client/tsconfig.json b/packages/angular-query-persist-client/tsconfig.json index b1366ab7700..f7c0a2343a8 100644 --- a/packages/angular-query-persist-client/tsconfig.json +++ b/packages/angular-query-persist-client/tsconfig.json @@ -15,7 +15,7 @@ "package.json" ], "references": [ - { "path": "../angular-query-experimental" }, + { "path": "../angular-query" }, { "path": "../query-persist-client-core" } ] } diff --git a/packages/angular-query-persist-client/vite.config.ts b/packages/angular-query-persist-client/vite.config.ts index 3c608b8a481..f362edc2bb4 100644 --- a/packages/angular-query-persist-client/vite.config.ts +++ b/packages/angular-query-persist-client/vite.config.ts @@ -1,11 +1,24 @@ +import path from 'node:path' +import { fileURLToPath } from 'node:url' import { defineConfig } from 'vitest/config' import packageJson from './package.json' +const packageDir = path.dirname(fileURLToPath(import.meta.url)) +const angularQueryEntry = path.join(packageDir, '../angular-query/src/index.ts') +const angularQueryInternalEntry = path.join( + packageDir, + '../angular-query/src/internal.ts', +) + export default defineConfig({ // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660 resolve: { conditions: ['@tanstack/custom-condition'], + alias: { + '@tanstack/angular-query/internal': angularQueryInternalEntry, + '@tanstack/angular-query': angularQueryEntry, + }, }, environments: { ssr: { diff --git a/packages/angular-query-experimental/.attw.json b/packages/angular-query/.attw.json similarity index 100% rename from packages/angular-query-experimental/.attw.json rename to packages/angular-query/.attw.json diff --git a/packages/angular-query-experimental/README.md b/packages/angular-query/README.md similarity index 62% rename from packages/angular-query-experimental/README.md rename to packages/angular-query/README.md index 53fea66deba..073022cc684 100644 --- a/packages/angular-query-experimental/README.md +++ b/packages/angular-query/README.md @@ -14,15 +14,13 @@ /> -[![npm version](https://img.shields.io/npm/v/@tanstack/angular-query-experimental)](https://www.npmjs.com/package/@tanstack/angular-query-experimental) -[![npm license](https://img.shields.io/npm/l/@tanstack/angular-query-experimental)](https://github.com/TanStack/query/blob/main/LICENSE) -[![bundle size](https://img.shields.io/bundlephobia/minzip/@tanstack/angular-query-experimental)](https://bundlephobia.com/package/@tanstack/angular-query-experimental) -[![npm](https://img.shields.io/npm/dm/@tanstack/angular-query-experimental)](https://www.npmjs.com/package/@tanstack/angular-query-experimental) +[![npm version](https://img.shields.io/npm/v/@tanstack/angular-query)](https://www.npmjs.com/package/@tanstack/angular-query) +[![npm license](https://img.shields.io/npm/l/@tanstack/angular-query)](https://github.com/TanStack/query/blob/main/LICENSE) +[![bundle size](https://img.shields.io/bundlephobia/minzip/@tanstack/angular-query)](https://bundlephobia.com/package/@tanstack/angular-query) +[![npm](https://img.shields.io/npm/dm/@tanstack/angular-query)](https://www.npmjs.com/package/@tanstack/angular-query) # Angular Query -> IMPORTANT: This library is currently in an experimental stage. This means that breaking changes may happen in minor AND patch releases. Upgrade carefully. If you use this in production while in experimental stage, please lock your version to a patch-level version to avoid unexpected breaking changes. - Functions for fetching, caching and updating asynchronous data in Angular # Documentation @@ -43,64 +41,48 @@ Visit https://tanstack.com/query/latest/docs/framework/angular/overview # Quick Start -> The Angular adapter for TanStack Query requires Angular 16 or higher. +> The Angular adapter for TanStack Query requires Angular 20.1 or higher. 1. Install `angular-query` ```bash -$ npm i @tanstack/angular-query-experimental +$ npm i @tanstack/angular-query ``` or ```bash -$ pnpm add @tanstack/angular-query-experimental +$ pnpm add @tanstack/angular-query ``` or ```bash -$ yarn add @tanstack/angular-query-experimental +$ yarn add @tanstack/angular-query ``` or ```bash -$ bun add @tanstack/angular-query-experimental +$ bun add @tanstack/angular-query ``` 2. Initialize **TanStack Query** by adding **provideTanStackQuery** to your application +Pass a factory; Angular runs it once per injector and in an injection context. + ```ts -import { provideTanStackQuery } from '@tanstack/angular-query-experimental' -import { QueryClient } from '@tanstack/angular-query-experimental' +import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query' bootstrapApplication(AppComponent, { - providers: [provideTanStackQuery(new QueryClient())], -}) -``` - -or in a NgModule-based app - -```ts -import { provideHttpClient } from '@angular/common/http' -import { - provideTanStackQuery, - QueryClient, -} from '@tanstack/angular-query-experimental' - -@NgModule({ - declarations: [AppComponent], - imports: [BrowserModule], - providers: [provideTanStackQuery(new QueryClient())], - bootstrap: [AppComponent], + providers: [provideTanStackQuery(() => new QueryClient())], }) ``` 3. Inject query ```ts -import { injectQuery } from '@tanstack/angular-query-experimental' +import { injectQuery } from '@tanstack/angular-query' import { Component } from '@angular/core' @Component({...}) @@ -145,5 +127,3 @@ export interface Post { body: string } ``` - - diff --git a/packages/angular-query-experimental/eslint.config.js b/packages/angular-query/eslint.config.js similarity index 100% rename from packages/angular-query-experimental/eslint.config.js rename to packages/angular-query/eslint.config.js diff --git a/packages/angular-query/package.json b/packages/angular-query/package.json new file mode 100644 index 00000000000..447dc7513d3 --- /dev/null +++ b/packages/angular-query/package.json @@ -0,0 +1,109 @@ +{ + "name": "@tanstack/angular-query", + "version": "4.0.0", + "description": "Signals for managing, caching and syncing asynchronous and remote data in Angular", + "author": "Arnoud de Vries", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/TanStack/query.git", + "directory": "packages/angular-query" + }, + "homepage": "https://tanstack.com/query", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "keywords": [ + "angular query", + "angular", + "cache", + "performance", + "reactive", + "signals", + "state management", + "state", + "tanstack" + ], + "scripts": { + "clean": "premove ./dist ./coverage ./dist-ts", + "compile": "tsc --build", + "test:eslint": "eslint --concurrency=auto ./src ./schematics ./schematics-build", + "test:types": "npm-run-all --serial test:types:*", + "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js --build", + "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js --build", + "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --build", + "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js --build", + "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js --build", + "test:types:tscurrent": "tsc --build", + "test:types:ts60": "node ../../node_modules/typescript60/lib/tsc.js --build", + "test:lib": "vitest", + "test:lib:zoneless": "vitest run", + "test:lib:zoneful": "vitest run --config vitest.zoneful.config.ts", + "test:lib:both": "pnpm run test:lib:zoneless && pnpm run test:lib:zoneful", + "test:lib:dev": "pnpm run test:lib --watch", + "test:build": "pnpm pack && pnpm run test:schematics && publint ./dist/*.tgz --strict && attw ./dist/*.tgz; premove ./dist/*.tgz", + "test:schematics": "vitest run --config vitest.schematics.config.ts", + "build": "vite build && tsc -p tsconfig.schematics.json && node scripts/inject-schematic-package-info.js", + "prepack": "node scripts/prepack.js" + }, + "type": "module", + "schematics": "./schematics/collection.json", + "ng-add": { + "save": "dependencies" + }, + "types": "dist/index.d.ts", + "module": "dist/index.mjs", + "exports": { + ".": { + "@tanstack/custom-condition": "./src/index.ts", + "types": "./dist/index.d.ts", + "default": "./dist/index.mjs" + }, + "./internal": { + "@tanstack/custom-condition": "./src/internal.ts", + "types": "./dist/internal.d.ts", + "default": "./dist/internal.mjs" + }, + "./package.json": "./package.json" + }, + "sideEffects": false, + "files": [ + "**/*.d.ts", + "**/*.mjs", + "**/*.mjs.map" + ], + "dependencies": { + "@tanstack/query-core": "workspace:*" + }, + "devDependencies": { + "@analogjs/vite-plugin-angular": "^2.3.1", + "@angular-devkit/schematics": "^22.0.0", + "@angular/build": "^22.0.0", + "@angular/common": "^22.0.0", + "@angular/compiler": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@angular/platform-server": "^22.0.0", + "@angular/router": "^22.0.0", + "@schematics/angular": "^22.0.0", + "@tanstack/query-test-utils": "workspace:*", + "@testing-library/angular": "^18.1.1", + "npm-run-all2": "^5.0.0", + "rxjs": "^7.8.2", + "typescript": "6.0.3", + "vite-plugin-dts": "4.2.3", + "vite-plugin-externalize-deps": "^0.9.0", + "vite-tsconfig-paths": "^5.1.4", + "zone.js": "^0.16.0" + }, + "peerDependencies": { + "@angular/common": ">=22.0.0", + "@angular/core": ">=22.0.0" + }, + "publishConfig": { + "directory": "dist", + "linkDirectory": false + } +} diff --git a/packages/angular-query-experimental/root.eslint.config.js b/packages/angular-query/root.eslint.config.js similarity index 100% rename from packages/angular-query-experimental/root.eslint.config.js rename to packages/angular-query/root.eslint.config.js diff --git a/packages/angular-query/schematics-build/ng-add.test.ts b/packages/angular-query/schematics-build/ng-add.test.ts new file mode 100644 index 00000000000..8417badae20 --- /dev/null +++ b/packages/angular-query/schematics-build/ng-add.test.ts @@ -0,0 +1,100 @@ +import { createRequire } from 'node:module' +import { dirname, resolve } from 'node:path' +import { describe, expect, it } from 'vitest' +import { SchematicTestRunner } from '@angular-devkit/schematics/testing' +import angularQueryPackage from '../package.json' with { type: 'json' } + +const require = createRequire(import.meta.url) +const angularRunner = new SchematicTestRunner( + '@schematics/angular', + resolve( + dirname(require.resolve('@schematics/angular/package.json')), + 'collection.json', + ), +) +const queryRunner = new SchematicTestRunner( + angularQueryPackage.name, + resolve('dist/schematics/collection.json'), +) + +async function createAngularApplication(standalone = true) { + let tree = await angularRunner.runSchematic('workspace', { + name: 'workspace', + version: '20.0.0', + newProjectRoot: 'projects', + }) + + tree = await angularRunner.runSchematic( + 'application', + { + name: 'test-app', + standalone, + routing: false, + style: 'css', + skipInstall: true, + }, + tree, + ) + + return tree +} + +describe('ng-add schematic', () => { + it('configures Angular Query and devtools', async () => { + const tree = await createAngularApplication() + const result = await queryRunner.runSchematic( + 'ng-add', + { project: 'test-app' }, + tree, + ) + const packageJson = JSON.parse(result.readContent('/package.json')) as { + dependencies: Record + } + const devtoolsPackageName = Object.keys(packageJson.dependencies).find( + (packageName) => packageName.endsWith('/angular-query-devtools'), + ) + const appConfig = result.readContent( + '/projects/test-app/src/app/app.config.ts', + ) + + expect(devtoolsPackageName).toBeDefined() + expect(appConfig).toContain(`from '${angularQueryPackage.name}'`) + expect(appConfig).toContain(`from '${devtoolsPackageName}'`) + expect(appConfig).toContain( + 'provideTanStackQuery(() => new QueryClient(), withDevtools())', + ) + expect(queryRunner.tasks).toEqual([ + expect.objectContaining({ name: 'node-package' }), + ]) + }) + + it.each([ + { applicationType: 'standalone', standalone: true }, + { applicationType: 'NgModule', standalone: false }, + ])( + 'does not duplicate configuration in a $applicationType application', + async ({ standalone }) => { + const tree = await createAngularApplication(standalone) + const firstResult = await queryRunner.runSchematic( + 'ng-add', + { project: 'test-app' }, + tree, + ) + const secondResult = await queryRunner.runSchematic( + 'ng-add', + { project: 'test-app' }, + firstResult, + ) + const applicationSources = secondResult.files + .filter((filePath) => filePath.endsWith('.ts')) + .map((filePath) => secondResult.readContent(filePath)) + .join('\n') + + expect(applicationSources.match(/provideTanStackQuery\(/g)).toHaveLength( + 1, + ) + expect(applicationSources.match(/withDevtools\(\)/g)).toHaveLength(1) + expect(queryRunner.tasks).toHaveLength(0) + }, + ) +}) diff --git a/packages/angular-query/schematics/collection.json b/packages/angular-query/schematics/collection.json new file mode 100644 index 00000000000..88f809203d4 --- /dev/null +++ b/packages/angular-query/schematics/collection.json @@ -0,0 +1,10 @@ +{ + "$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json", + "schematics": { + "ng-add": { + "description": "Configure TanStack Query in an Angular application.", + "factory": "./ng-add/index#ngAdd", + "schema": "./ng-add/schema.json" + } + } +} diff --git a/packages/angular-query/schematics/ng-add/index.ts b/packages/angular-query/schematics/ng-add/index.ts new file mode 100644 index 00000000000..e5eb0b34d8a --- /dev/null +++ b/packages/angular-query/schematics/ng-add/index.ts @@ -0,0 +1,143 @@ +import { addRootProvider } from '@schematics/angular/utility' +import { + NodeDependencyType, + addPackageJsonDependency, +} from '@schematics/angular/utility/dependencies' +import { + getAppModulePath, + isStandaloneApp, +} from '@schematics/angular/utility/ng-ast-utils' +import { findAppConfig } from '@schematics/angular/utility/standalone/app_config' +import { + findBootstrapApplicationCall, + getMainFilePath, +} from '@schematics/angular/utility/standalone/util' +import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks' +import { chain } from '@angular-devkit/schematics' +import ts from 'typescript' +import type { Rule, Tree } from '@angular-devkit/schematics' +import type { Schema } from './schema' + +// Replaced with package metadata by scripts/inject-schematic-package-info.js. +// The published schematic contains literal values and does not read package.json. +const PACKAGE_NAME = '__ANGULAR_QUERY_PACKAGE_NAME__' +const DEVTOOLS_PACKAGE_NAME = '__ANGULAR_QUERY_DEVTOOLS_PACKAGE_NAME__' +const DEVTOOLS_PACKAGE_VERSION = '__ANGULAR_QUERY_DEVTOOLS_PACKAGE_VERSION__' + +function hasPackageDependency(tree: Tree, name: string) { + const packageJsonPath = tree.exists('/package.json') + ? '/package.json' + : 'package.json' + const packageJson = JSON.parse(tree.readText(packageJsonPath)) as Record< + string, + Record | undefined + > + + return ['dependencies', 'devDependencies', 'optionalDependencies'].some( + (dependencyType) => packageJson[dependencyType]?.[name] !== undefined, + ) +} + +function addDevtoolsDependency(): Rule { + return (tree, context) => { + if (hasPackageDependency(tree, DEVTOOLS_PACKAGE_NAME)) return tree + + addPackageJsonDependency(tree, { + type: NodeDependencyType.Default, + name: DEVTOOLS_PACKAGE_NAME, + version: DEVTOOLS_PACKAGE_VERSION, + overwrite: false, + }) + context.addTask(new NodePackageInstallTask()) + return tree + } +} + +function hasProviderCall(tree: Tree, sourcePath: string) { + const source = ts.createSourceFile( + sourcePath, + tree.readText(sourcePath), + ts.ScriptTarget.Latest, + true, + ) + const localProviderNames = new Set() + + for (const statement of source.statements) { + if ( + !ts.isImportDeclaration(statement) || + !ts.isStringLiteral(statement.moduleSpecifier) || + statement.moduleSpecifier.text !== PACKAGE_NAME || + !statement.importClause?.namedBindings || + !ts.isNamedImports(statement.importClause.namedBindings) + ) { + continue + } + + for (const element of statement.importClause.namedBindings.elements) { + if ( + (element.propertyName ?? element.name).text === 'provideTanStackQuery' + ) { + localProviderNames.add(element.name.text) + } + } + } + + if (localProviderNames.size === 0) return false + + let found = false + const visit = (node: ts.Node) => { + if ( + ts.isCallExpression(node) && + ts.isIdentifier(node.expression) && + localProviderNames.has(node.expression.text) + ) { + found = true + return + } + + if (!found) ts.forEachChild(node, visit) + } + visit(source) + return found +} + +async function hasRootQueryProvider(tree: Tree, projectName: string) { + const mainFilePath = await getMainFilePath(tree, projectName) + const rootFilePath = isStandaloneApp(tree, mainFilePath) + ? (findAppConfig( + findBootstrapApplicationCall(tree, mainFilePath), + tree, + mainFilePath, + )?.filePath ?? mainFilePath) + : getAppModulePath(tree, mainFilePath) + + return hasProviderCall(tree, rootFilePath) +} + +function addQueryProvider(project: string): Rule { + return async (tree) => { + if (await hasRootQueryProvider(tree, project)) return tree + + return addRootProvider( + project, + ({ code, external }) => + code`${external( + 'provideTanStackQuery', + PACKAGE_NAME, + )}(() => new ${external( + 'QueryClient', + PACKAGE_NAME, + )}(), ${external('withDevtools', DEVTOOLS_PACKAGE_NAME)}())`, + ) + } +} + +/** + * Configures TanStack Query at the application root. + * + * The QueryClient factory is resolved by each root injector, preventing query + * caches from being shared between SSR requests. + */ +export function ngAdd(options: Schema): Rule { + return chain([addDevtoolsDependency(), addQueryProvider(options.project)]) +} diff --git a/packages/angular-query/schematics/ng-add/schema.json b/packages/angular-query/schematics/ng-add/schema.json new file mode 100644 index 00000000000..0585b15541e --- /dev/null +++ b/packages/angular-query/schematics/ng-add/schema.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "TanStackAngularQueryNgAdd", + "title": "TanStack Angular Query ng-add options", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The Angular project to configure.", + "$default": { + "$source": "projectName" + } + } + }, + "required": ["project"], + "additionalProperties": false +} diff --git a/packages/angular-query/schematics/ng-add/schema.ts b/packages/angular-query/schematics/ng-add/schema.ts new file mode 100644 index 00000000000..748d4572c17 --- /dev/null +++ b/packages/angular-query/schematics/ng-add/schema.ts @@ -0,0 +1,3 @@ +export interface Schema { + project: string +} diff --git a/packages/angular-query/schematics/package.json b/packages/angular-query/schematics/package.json new file mode 100644 index 00000000000..5bbefffbabe --- /dev/null +++ b/packages/angular-query/schematics/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/packages/angular-query/scripts/inject-schematic-package-info.js b/packages/angular-query/scripts/inject-schematic-package-info.js new file mode 100644 index 00000000000..c2911f1ef2e --- /dev/null +++ b/packages/angular-query/scripts/inject-schematic-package-info.js @@ -0,0 +1,47 @@ +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +const packageDir = path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + '..', +) +const queryPackage = readPackageJson(path.join(packageDir, 'package.json')) +const devtoolsPackage = readPackageJson( + path.resolve(packageDir, '../angular-query-devtools/package.json'), +) + +const outputPath = path.join(packageDir, 'dist/schematics/ng-add/index.js') +let output = fs.readFileSync(outputPath, 'utf8') + +const replacements = new Map([ + ['__ANGULAR_QUERY_PACKAGE_NAME__', queryPackage.name], + ['__ANGULAR_QUERY_DEVTOOLS_PACKAGE_NAME__', devtoolsPackage.name], + ['__ANGULAR_QUERY_DEVTOOLS_PACKAGE_VERSION__', devtoolsPackage.version], +]) + +for (const [placeholder, value] of replacements) { + if (output.includes(placeholder)) { + output = output.replaceAll(placeholder, value) + } else if (!output.includes(value)) { + throw new Error( + `Could not find ${placeholder} or its expected value in ${outputPath}.`, + ) + } +} + +fs.writeFileSync(outputPath, output) + +/** + * @param {string} packageJsonPath + * @returns {{ name: string; version: string }} + */ +function readPackageJson(packageJsonPath) { + const value = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) + + if (typeof value.name !== 'string' || typeof value.version !== 'string') { + throw new Error(`Invalid package metadata in ${packageJsonPath}.`) + } + + return value +} diff --git a/packages/angular-query/scripts/prepack.js b/packages/angular-query/scripts/prepack.js new file mode 100644 index 00000000000..033e008dc09 --- /dev/null +++ b/packages/angular-query/scripts/prepack.js @@ -0,0 +1,116 @@ +import fs from 'node:fs' +import path from 'node:path' +import './inject-schematic-package-info.js' + +/** + * Prepack script that prepares the package for publishing by: + * 1. Creating a modified package.json without dev dependencies, publishConfig and build scripts + * 2. Updating file paths to remove 'dist/' prefixes (since files will be at root in published package) + * 3. Writing this modified package.json to the `dist` directory + * 4. Copying additional files like README.md to the dist directory + * + * Type declarations need to be in the package root or corresponding sub-path to support + * sub-path exports in applications still using `moduleResolution: node`. + */ + +console.log('Running prepack script') + +/** + * Files to copy to the dist directory + * @type {string[]} + */ +const FILES_TO_COPY = [ + 'README.md', + 'schematics/collection.json', + 'schematics/package.json', + 'schematics/ng-add/schema.json', +] + +/** + * Fields to remove from the package.json copy + * @type {string[]} + */ +const FIELDS_TO_REMOVE = [ + 'devDependencies', + 'files', + 'publishConfig', + 'scripts', +] + +/** + * Replaces 'dist/' or './dist/' prefix from a file path with './' + * Only matches at the start of the path to avoid false matches + * @param {string} filePath - The file path to process + * @returns {string} The path without dist prefix + */ +function replaceDist(filePath) { + // Only match dist/ at the beginning of the path, followed by a filename + // This prevents matching strings like "distributed/file.js" or "some/dist/path" + return filePath.replace(/^(?:\.\/)?dist\/(?=.+)/, './') +} + +/** + * Recursively processes package.json `exports` to remove dist prefixes + * @param {Record} exports - The exports object to process + * @returns {Record} The processed exports object + */ +function processExports(exports) { + return Object.fromEntries( + Object.entries(exports) + .filter(([key]) => key !== '@tanstack/custom-condition') + .map(([key, value]) => [ + key, + typeof value === 'string' + ? replaceDist(value) + : typeof value === 'object' && value !== null + ? processExports(value) + : value, + ]), + ) +} + +console.log('Copying modified package.json') + +/** @type {Record} */ +const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8')) + +const modifiedPackageJson = { ...packageJson } + +if (modifiedPackageJson.types) { + modifiedPackageJson.types = replaceDist(modifiedPackageJson.types) +} + +if (modifiedPackageJson.module) { + modifiedPackageJson.module = replaceDist(modifiedPackageJson.module) +} + +if (modifiedPackageJson.exports) { + modifiedPackageJson.exports = processExports(modifiedPackageJson.exports) +} + +for (const field of FIELDS_TO_REMOVE) { + delete modifiedPackageJson[field] +} + +if (!fs.existsSync('dist')) { + fs.mkdirSync('dist', { recursive: true }) +} + +fs.writeFileSync( + path.join('dist', 'package.json'), + JSON.stringify(modifiedPackageJson, null, 2), +) + +console.log('Copying other files') +for (const file of FILES_TO_COPY) { + if (fs.existsSync(file)) { + const destination = path.join('dist', file) + fs.mkdirSync(path.dirname(destination), { recursive: true }) + fs.copyFileSync(file, destination) + console.log(`${file}`) + } else { + console.log(`${file} not found, skipping`) + } +} + +console.log('prepack complete') diff --git a/packages/angular-query-experimental/src/__tests__/infinite-query-options.test-d.ts b/packages/angular-query/src/__tests__/infinite-query-options.test-d.ts similarity index 100% rename from packages/angular-query-experimental/src/__tests__/infinite-query-options.test-d.ts rename to packages/angular-query/src/__tests__/infinite-query-options.test-d.ts diff --git a/packages/angular-query-experimental/src/__tests__/infinite-query-options.test.ts b/packages/angular-query/src/__tests__/infinite-query-options.test.ts similarity index 100% rename from packages/angular-query-experimental/src/__tests__/infinite-query-options.test.ts rename to packages/angular-query/src/__tests__/infinite-query-options.test.ts diff --git a/packages/angular-query/src/__tests__/inject-infinite-query.test-d.ts b/packages/angular-query/src/__tests__/inject-infinite-query.test-d.ts new file mode 100644 index 00000000000..4ea0a46baf3 --- /dev/null +++ b/packages/angular-query/src/__tests__/inject-infinite-query.test-d.ts @@ -0,0 +1,176 @@ +import { describe, expectTypeOf, it } from 'vitest' +import { injectInfiniteQuery, skipToken, toResource } from '..' +import type { CreateInfiniteQueryOptions } from '..' +import type { Signal } from '@angular/core' +import type { InfiniteData } from '@tanstack/query-core' + +describe('injectInfiniteQuery', () => { + it('should expose status predicates as Angular signals', () => { + const query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => Promise.resolve('data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + })) + + expectTypeOf(query.isSuccess).toMatchTypeOf>() + expectTypeOf(query.isError).toMatchTypeOf>() + expectTypeOf(query.isPending).toMatchTypeOf>() + }) + + describe('initialData', () => { + it('should narrow a defined result after an isError check', () => { + const query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + Promise.resolve('data on page ' + pageParam), + initialData: { pages: ['initial data'], pageParams: [0] }, + initialPageParam: 0, + getNextPageParam: () => 12, + })) + + if (query.isError()) { + expectTypeOf(query.error).toEqualTypeOf>() + } + + expectTypeOf(toResource(query).value).toEqualTypeOf< + Signal> + >() + + // @ts-expect-error Resources are created explicitly with toResource. + query.resource + }) + + it('should keep data possibly undefined when initialData is undefined', () => { + const query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + Promise.resolve('data on page ' + pageParam), + initialData: undefined, + initialPageParam: 0, + getNextPageParam: () => 12, + })) + + expectTypeOf(query.data).toEqualTypeOf< + Signal | Signal> + >() + }) + }) + + describe('Discriminated union return type', () => { + it('data should be possibly undefined by default', () => { + const query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + Promise.resolve('data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + })) + + expectTypeOf(query.data).toEqualTypeOf< + Signal | Signal> + >() + }) + + it('data should be defined when query is success', () => { + const query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + Promise.resolve('data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + })) + + if (query.isSuccess()) { + expectTypeOf(query.data).toEqualTypeOf< + Signal> + >() + expectTypeOf(toResource(query).value).toEqualTypeOf< + Signal> + >() + } + }) + + it('error should be null when query is success', () => { + const query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + Promise.resolve('data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + })) + + if (query.isSuccess()) { + expectTypeOf(query.error).toEqualTypeOf>() + } + }) + + it('data should be undefined when query is pending', () => { + const query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + Promise.resolve('data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + })) + + if (query.isPending()) { + expectTypeOf(query.data).toEqualTypeOf>() + } + }) + + it('error should be defined when query is error', () => { + const query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + Promise.resolve('data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + })) + + if (query.isError()) { + expectTypeOf(query.error).toEqualTypeOf>() + } + }) + }) + + it('should provide the correct types to the select function', () => { + const query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => Promise.resolve('data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + select: (data) => { + expectTypeOf(data).toEqualTypeOf>() + return data + }, + })) + + expectTypeOf(query.data).toEqualTypeOf< + Signal | Signal> + >() + }) + + it('should work when queryFn is skipToken', () => { + const query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: skipToken, + initialPageParam: 0, + getNextPageParam: () => 1, + })) + + // TPageParam falls back to `unknown` here (unlike `infiniteQueryOptions`, which infers + // `number` for the same options) because there's no skipToken-specific overload to carry it. + expectTypeOf(query.data()).toEqualTypeOf< + InfiniteData | undefined + >() + }) +}) + +describe('injectInfiniteQuery options', () => { + it('omits observer error reporting options', () => { + expectTypeOf().not.toHaveProperty( + 'throwOnError', + ) + }) +}) diff --git a/packages/angular-query/src/__tests__/inject-infinite-query.test.ts b/packages/angular-query/src/__tests__/inject-infinite-query.test.ts new file mode 100644 index 00000000000..0ad7203b095 --- /dev/null +++ b/packages/angular-query/src/__tests__/inject-infinite-query.test.ts @@ -0,0 +1,188 @@ +import { TestBed } from '@angular/core/testing' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { ChangeDetectionStrategy, Component, signal } from '@angular/core' +import { sleep } from '@tanstack/query-test-utils' +import { QueryClient, injectInfiniteQuery, skipToken } from '..' +import { expectSignals, setupTanStackQueryTestBed } from './test-utils' + +describe('injectInfiniteQuery', () => { + let queryClient: QueryClient + + beforeEach(() => { + queryClient = new QueryClient() + vi.useFakeTimers() + setupTanStackQueryTestBed(queryClient) + }) + + afterEach(() => { + vi.useRealTimers() + }) + + it.each(['refetch', 'fetchNextPage', 'fetchPreviousPage'] as const)( + 'applies current infinite-query options before %s', + async (method) => { + vi.useRealTimers() + const version = signal('old') + const query = TestBed.runInInjectionContext(() => + injectInfiniteQuery(() => { + const current = version() + return { + queryKey: ['infinite'], + enabled: false, + initialPageParam: 0, + initialData: { pages: ['initial'], pageParams: [0] }, + getNextPageParam: () => 1, + getPreviousPageParam: () => -1, + queryFn: async () => current, + } + }), + ) + query.data() + const execute = query[method] + version.set('new') + const result = await execute() + expect(result.data?.pages).toContain('new') + expect(result.data?.pages).not.toContain('old') + }, + ) + + it('should properly execute infinite query', async () => { + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + sleep(10).then(() => 'data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + expectSignals(query, { + data: undefined, + status: 'pending', + }) + + await vi.advanceTimersByTimeAsync(11) + + expectSignals(query, { + data: { + pageParams: [0], + pages: ['data on page 0'], + }, + status: 'success', + }) + + void query.fetchNextPage() + + await vi.advanceTimersByTimeAsync(11) + + expectSignals(query, { + data: { + pageParams: [0, 12], + pages: ['data on page 0', 'data on page 12'], + }, + status: 'success', + }) + }) + + it('should keep initialData visible alongside the error when a refetch fails', async () => { + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectInfiniteQuery(() => ({ + queryKey: ['infiniteInitialDataError'], + queryFn: () => + sleep(10).then(() => Promise.reject(new Error('Some error'))), + initialData: { pages: [1], pageParams: [1] }, + getNextPageParam: (lastPage: number) => lastPage + 1, + initialPageParam: 0, + retry: false, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + expect(query.data()?.pages).toEqual([1]) + expect(query.isError()).toBe(false) + expect(query.status()).toBe('success') + + await vi.advanceTimersByTimeAsync(11) + fixture.detectChanges() + + expect(query.data()?.pages).toEqual([1]) + expect(query.isError()).toBe(true) + expect(query.status()).toBe('error') + }) + + it('should not fetch when queryFn is skipToken, and fetch once it is replaced', async () => { + const queryFn = vi.fn(({ pageParam }: { pageParam: number }) => + sleep(10).then(() => `comments for 1 page ${pageParam}`), + ) + const postId = signal(undefined) + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectInfiniteQuery(() => ({ + queryKey: ['skipTokenInfinite'], + queryFn: postId() != null ? queryFn : skipToken, + initialPageParam: 0, + getNextPageParam: () => 12, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + expect(query.status()).toBe('pending') + expect(query.isFetching()).toBe(false) + + await vi.advanceTimersByTimeAsync(11) + fixture.detectChanges() + expect(queryFn).not.toHaveBeenCalled() + expect(query.status()).toBe('pending') + expect(query.isFetching()).toBe(false) + + postId.set('1') + fixture.detectChanges() + expect(query.isFetching()).toBe(true) + + await vi.advanceTimersByTimeAsync(11) + fixture.detectChanges() + expect(queryFn).toHaveBeenCalledTimes(1) + expect(query.status()).toBe('success') + expect(query.data()?.pages).toEqual(['comments for 1 page 0']) + }) + + describe('injection context', () => { + it('throws NG0203 with descriptive error outside injection context', () => { + expect(() => { + injectInfiniteQuery(() => ({ + queryKey: ['injectionContextError'], + queryFn: ({ pageParam }) => + sleep(0).then(() => 'data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + })) + }).toThrowError(/NG0203(.*?)injectInfiniteQuery/) + }) + }) +}) diff --git a/packages/angular-query-experimental/src/__tests__/inject-is-fetching.test.ts b/packages/angular-query/src/__tests__/inject-is-fetching.test.ts similarity index 64% rename from packages/angular-query-experimental/src/__tests__/inject-is-fetching.test.ts rename to packages/angular-query/src/__tests__/inject-is-fetching.test.ts index db1f7aeea11..411e261a1be 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-is-fetching.test.ts +++ b/packages/angular-query/src/__tests__/inject-is-fetching.test.ts @@ -1,10 +1,6 @@ import { TestBed } from '@angular/core/testing' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { - Component, - Injector, - provideZonelessChangeDetection, -} from '@angular/core' +import { Component, input, inputBinding, signal } from '@angular/core' import { render } from '@testing-library/angular' import { queryKey, sleep } from '@tanstack/query-test-utils' import { @@ -13,6 +9,7 @@ import { injectQuery, provideTanStackQuery, } from '..' +import { provideAngularQueryChangeDetection } from './test-utils' describe('injectIsFetching', () => { let queryClient: QueryClient @@ -23,8 +20,8 @@ describe('injectIsFetching', () => { TestBed.configureTestingModule({ providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), ], }) }) @@ -49,10 +46,6 @@ describe('injectIsFetching', () => { const rendered = await render(Page) - expect(rendered.getByText('fetching: 0')).toBeInTheDocument() - - await vi.advanceTimersByTimeAsync(0) - rendered.fixture.detectChanges() expect(rendered.getByText('fetching: 1')).toBeInTheDocument() await vi.advanceTimersByTimeAsync(101) @@ -60,6 +53,12 @@ describe('injectIsFetching', () => { expect(rendered.getByText('fetching: 0')).toBeInTheDocument() }) + it('should return a read-only signal', () => { + const isFetching = TestBed.runInInjectionContext(() => injectIsFetching()) + + expect(isFetching).not.toHaveProperty('set') + }) + it('should be able to filter by queryKey', async () => { const key1 = queryKey() const key2 = queryKey() @@ -76,7 +75,7 @@ describe('injectIsFetching', () => { queryKey: key2, queryFn: () => sleep(100).then(() => 'test2'), })) - readonly isFetching = injectIsFetching({ queryKey: key1 }) + readonly isFetching = injectIsFetching(() => ({ queryKey: key1 })) } const rendered = await render(Page) @@ -90,19 +89,43 @@ describe('injectIsFetching', () => { expect(rendered.getByText('fetching: 0')).toBeInTheDocument() }) + it('should support signal reads in filter predicates', async () => { + const key = queryKey() + + void queryClient.query({ + queryKey: key, + queryFn: () => sleep(100).then(() => 'data'), + }) + + @Component({ + template: `
fetching: {{ isFetching() }}
`, + }) + class Page { + readonly includeQuery = input.required() + readonly isFetching = injectIsFetching(() => ({ + predicate: () => this.includeQuery(), + })) + } + + const subscribe = vi.spyOn(queryClient.getQueryCache(), 'subscribe') + const includeQuery = signal(true) + const rendered = await render(Page, { + bindings: [inputBinding('includeQuery', includeQuery)], + }) + + expect(rendered.getByText('fetching: 1')).toBeInTheDocument() + + includeQuery.set(false) + rendered.fixture.detectChanges() + expect(subscribe).toHaveBeenCalledTimes(1) + expect(rendered.getByText('fetching: 0')).toBeInTheDocument() + }) + describe('injection context', () => { it('should throw NG0203 with descriptive error outside injection context', () => { expect(() => { injectIsFetching() }).toThrow(/NG0203(.*?)injectIsFetching/) }) - - it('should be usable outside injection context when passing an injector', () => { - expect( - injectIsFetching(undefined, { - injector: TestBed.inject(Injector), - }), - ).not.toThrow() - }) }) }) diff --git a/packages/angular-query-experimental/src/__tests__/inject-is-mutating.test.ts b/packages/angular-query/src/__tests__/inject-is-mutating.test.ts similarity index 67% rename from packages/angular-query-experimental/src/__tests__/inject-is-mutating.test.ts rename to packages/angular-query/src/__tests__/inject-is-mutating.test.ts index 66fe678d03a..3bc7767be38 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-is-mutating.test.ts +++ b/packages/angular-query/src/__tests__/inject-is-mutating.test.ts @@ -1,10 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { TestBed } from '@angular/core/testing' -import { - Component, - Injector, - provideZonelessChangeDetection, -} from '@angular/core' +import { Component, input, inputBinding, signal } from '@angular/core' import { render } from '@testing-library/angular' import { queryKey, sleep } from '@tanstack/query-test-utils' import { @@ -13,6 +9,7 @@ import { injectMutation, provideTanStackQuery, } from '..' +import { provideAngularQueryChangeDetection } from './test-utils' describe('injectIsMutating', () => { let queryClient: QueryClient @@ -23,8 +20,8 @@ describe('injectIsMutating', () => { TestBed.configureTestingModule({ providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), ], }) }) @@ -78,7 +75,7 @@ describe('injectIsMutating', () => { mutationKey: key2, mutationFn: () => sleep(100).then(() => 'data2'), })) - readonly isMutating = injectIsMutating({ mutationKey: key1 }) + readonly isMutating = injectIsMutating(() => ({ mutationKey: key1 })) } const rendered = await render(Page) @@ -95,19 +92,41 @@ describe('injectIsMutating', () => { expect(rendered.getByText('mutating: 0')).toBeInTheDocument() }) + it('should support signal reads in filter predicates', async () => { + const mutation = queryClient.getMutationCache().build(queryClient, { + mutationFn: () => sleep(100).then(() => 'data'), + }) + void mutation.execute(undefined) + + @Component({ + template: `
mutating: {{ isMutating() }}
`, + }) + class Page { + readonly includeMutation = input.required() + readonly isMutating = injectIsMutating(() => ({ + predicate: () => this.includeMutation(), + })) + } + + const subscribe = vi.spyOn(queryClient.getMutationCache(), 'subscribe') + const includeMutation = signal(true) + const rendered = await render(Page, { + bindings: [inputBinding('includeMutation', includeMutation)], + }) + + expect(rendered.getByText('mutating: 1')).toBeInTheDocument() + + includeMutation.set(false) + rendered.fixture.detectChanges() + expect(subscribe).toHaveBeenCalledTimes(1) + expect(rendered.getByText('mutating: 0')).toBeInTheDocument() + }) + describe('injection context', () => { it('should throw NG0203 with descriptive error outside injection context', () => { expect(() => { injectIsMutating() }).toThrow(/NG0203(.*?)injectIsMutating/) }) - - it('should be usable outside injection context when passing an injector', () => { - expect( - injectIsMutating(undefined, { - injector: TestBed.inject(Injector), - }), - ).not.toThrow() - }) }) }) diff --git a/packages/angular-query/src/__tests__/inject-is-restoring.test.ts b/packages/angular-query/src/__tests__/inject-is-restoring.test.ts new file mode 100644 index 00000000000..ca55f78a03e --- /dev/null +++ b/packages/angular-query/src/__tests__/inject-is-restoring.test.ts @@ -0,0 +1,51 @@ +import { TestBed } from '@angular/core/testing' +import { describe, expect, it } from 'vitest' +import { InjectionToken, inject, signal } from '@angular/core' +import { provideIsRestoring } from '../internal' +import { QueryClient, injectIsRestoring, provideTanStackQuery } from '..' +import { provideAngularQueryChangeDetection } from './test-utils' + +describe('injectIsRestoring', () => { + let queryClient: QueryClient + + it('returns false by default when provideIsRestoring is not used', () => { + queryClient = new QueryClient() + + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + + const isRestoring = TestBed.runInInjectionContext(() => { + return injectIsRestoring() + }) + + expect(isRestoring()).toBe(false) + }) + + it('resolves a restoration signal factory in the injection context', () => { + const state = signal(true) + const token = new InjectionToken('restoration state') + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + { provide: token, useValue: state }, + provideIsRestoring(() => inject(token).asReadonly()), + ], + }) + + const isRestoring = TestBed.runInInjectionContext(injectIsRestoring) + expect(isRestoring()).toBe(true) + state.set(false) + expect(isRestoring()).toBe(false) + expect(TestBed.runInInjectionContext(injectIsRestoring)).toBe(isRestoring) + }) + + it('throws NG0203 with descriptive error outside injection context', () => { + expect(() => { + injectIsRestoring() + }).toThrow(/NG0203(.*?)injectIsRestoring/) + }) +}) diff --git a/packages/angular-query-experimental/src/__tests__/inject-mutation-state.test-d.ts b/packages/angular-query/src/__tests__/inject-mutation-state.test-d.ts similarity index 54% rename from packages/angular-query-experimental/src/__tests__/inject-mutation-state.test-d.ts rename to packages/angular-query/src/__tests__/inject-mutation-state.test-d.ts index 0fbd5d8f652..7fbf73c47ac 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-mutation-state.test-d.ts +++ b/packages/angular-query/src/__tests__/inject-mutation-state.test-d.ts @@ -1,6 +1,6 @@ import { describe, expectTypeOf, it } from 'vitest' import { injectMutationState } from '..' -import type { MutationState, MutationStatus } from '..' +import type { Mutation, MutationState, MutationStatus } from '..' describe('injectMutationState', () => { it('should default to QueryState', () => { @@ -19,4 +19,22 @@ describe('injectMutationState', () => { expectTypeOf(result()).toEqualTypeOf>() }) + + it('should infer the mutation type from a mutation-state result', () => { + type Result = MutationState< + string, + Error, + { id: number }, + { previous: string } + > + + injectMutationState(() => ({ + select: (mutation) => { + expectTypeOf(mutation).toEqualTypeOf< + Mutation + >() + return mutation.state + }, + })) + }) }) diff --git a/packages/angular-query-experimental/src/__tests__/inject-mutation-state.test.ts b/packages/angular-query/src/__tests__/inject-mutation-state.test.ts similarity index 55% rename from packages/angular-query-experimental/src/__tests__/inject-mutation-state.test.ts rename to packages/angular-query/src/__tests__/inject-mutation-state.test.ts index 4eee7699aeb..89f0330bb94 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-mutation-state.test.ts +++ b/packages/angular-query/src/__tests__/inject-mutation-state.test.ts @@ -1,21 +1,21 @@ import { + ChangeDetectionStrategy, Component, - Injector, input, - provideZonelessChangeDetection, + inputBinding, signal, } from '@angular/core' import { TestBed } from '@angular/core/testing' +import { render } from '@testing-library/angular' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { By } from '@angular/platform-browser' -import { queryKey, sleep } from '@tanstack/query-test-utils' +import { sleep } from '@tanstack/query-test-utils' import { QueryClient, injectMutation, injectMutationState, provideTanStackQuery, } from '..' -import { setFixtureSignalInputs } from './test-utils' +import { provideAngularQueryChangeDetection } from './test-utils' describe('injectMutationState', () => { let queryClient: QueryClient @@ -25,8 +25,8 @@ describe('injectMutationState', () => { vi.useFakeTimers() TestBed.configureTestingModule({ providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), ], }) }) @@ -35,9 +35,50 @@ describe('injectMutationState', () => { vi.useRealTimers() }) + it('publishes selected mutation values unchanged and compares snapshot entries by identity', () => { + const version = signal('before') + queryClient.getMutationCache().build(queryClient, { mutationKey: ['a'] }) + queryClient.getMutationCache().build(queryClient, { mutationKey: ['b'] }) + let selected: Array<{ value: string }> = [] + const states = TestBed.runInInjectionContext(() => + injectMutationState(() => { + selected = [] + return { + select: (m) => { + const value = { + value: + m.options.mutationKey![0] === 'a' ? version() : 'unchanged', + } + selected.push(value) + return value + }, + } + }), + ) + const before = states() + version.set('after') + const after = states() + expect(after[0]).toBe(selected[0]) + expect(after[1]).toBe(selected[1]) + expect(after[1]).not.toBe(before[1]) + // Stable entries avoid array-only updates, without deep comparison. + const filter = signal('a') + const selectedValue = { value: 'same' } + const filtered = TestBed.runInInjectionContext(() => + injectMutationState(() => ({ + filters: { mutationKey: [filter()] }, + select: () => selectedValue, + })), + ) + const initial = filtered() + filter.set('b') + expect(filtered()).toBe(initial) + expect(filtered()[0]).toBe(selectedValue) + }) + describe('injectMutationState', () => { it('should return variables after calling mutate 1', () => { - const mutationKey = queryKey() + const mutationKey = ['mutation'] const variables = 'foo123' const mutation = TestBed.runInInjectionContext(() => { @@ -59,9 +100,9 @@ describe('injectMutationState', () => { expect(mutationState()).toEqual([variables]) }) - it('should update injectMutationState when reactive options change', () => { - const mutationKey1 = queryKey() - const mutationKey2 = queryKey() + it('reactive options should update injectMutationState', () => { + const mutationKey1 = ['mutation1'] + const mutationKey2 = ['mutation2'] const variables1 = 'foo123' const variables2 = 'bar234' @@ -96,9 +137,28 @@ describe('injectMutationState', () => { expect(mutationState()).toEqual([variables2]) }) + it('preserves result identity when an unrelated mutation changes', () => { + const mutationState = TestBed.runInInjectionContext(() => + injectMutationState(() => ({ + filters: { mutationKey: ['matching'] }, + })), + ) + const unrelatedMutation = TestBed.runInInjectionContext(() => + injectMutation(() => ({ + mutationKey: ['unrelated'], + mutationFn: () => Promise.resolve(), + })), + ) + const initialResult = mutationState() + + unrelatedMutation.mutate() + + expect(mutationState()).toBe(initialResult) + }) + it('should return variables after calling mutate 2', () => { queryClient.clear() - const mutationKey = queryKey() + const mutationKey = ['mutation'] const variables = 'bar234' const mutation = TestBed.runInInjectionContext(() => { @@ -145,6 +205,7 @@ describe('injectMutationState', () => { {{ mutation.status }} } `, + changeDetection: ChangeDetectionStrategy.OnPush, }) class FakeComponent { name = input.required() @@ -157,41 +218,34 @@ describe('injectMutationState', () => { })) } - const fixture = TestBed.createComponent(FakeComponent) - const { debugElement } = fixture - setFixtureSignalInputs(fixture, { name: fakeName }) - await vi.advanceTimersByTimeAsync(0) + TestBed.resetTestingModule() + const name = signal(fakeName) + const rendered = await render(FakeComponent, { + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + bindings: [inputBinding('name', name.asReadonly())], + detectChangesOnRender: false, + }) + rendered.fixture.detectChanges() - let spans = debugElement - .queryAll(By.css('span')) - .map((span) => span.nativeNode.textContent) + await vi.advanceTimersByTimeAsync(0) - expect(spans).toEqual(['pending', 'pending']) + expect(rendered.getAllByText('pending')).toHaveLength(2) await vi.advanceTimersByTimeAsync(11) - fixture.detectChanges() - - spans = debugElement - .queryAll(By.css('span')) - .map((span) => span.nativeNode.textContent) + rendered.fixture.detectChanges() - expect(spans).toEqual(['success', 'error']) + expect(rendered.getByText('success')).toBeInTheDocument() + expect(rendered.getByText('error')).toBeInTheDocument() }) describe('injection context', () => { - it('should throw NG0203 with descriptive error outside injection context', () => { + it('throws NG0203 with descriptive error outside injection context', () => { expect(() => { injectMutationState() - }).toThrow(/NG0203(.*?)injectMutationState/) - }) - - it('should be usable outside injection context when passing an injector', () => { - const injector = TestBed.inject(Injector) - expect( - injectMutationState(undefined, { - injector, - }), - ).not.toThrow() + }).toThrowError(/NG0203(.*?)injectMutationState/) }) }) }) diff --git a/packages/angular-query-experimental/src/__tests__/inject-mutation.test-d.ts b/packages/angular-query/src/__tests__/inject-mutation.test-d.ts similarity index 95% rename from packages/angular-query-experimental/src/__tests__/inject-mutation.test-d.ts rename to packages/angular-query/src/__tests__/inject-mutation.test-d.ts index cae6bac1af6..489fa0302c1 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-mutation.test-d.ts +++ b/packages/angular-query/src/__tests__/inject-mutation.test-d.ts @@ -1,6 +1,7 @@ import { describe, expectTypeOf, it } from 'vitest' import { sleep } from '@tanstack/query-test-utils' import { injectMutation } from '..' +import type { CreateMutationOptions } from '..' import type { Signal } from '@angular/core' import type { MutationFunctionContext, @@ -156,3 +157,9 @@ describe('injectMutation', () => { })) }) }) + +describe('injectMutation options', () => { + it('omits observer error reporting options', () => { + expectTypeOf().not.toHaveProperty('throwOnError') + }) +}) diff --git a/packages/angular-query-experimental/src/__tests__/inject-mutation.test.ts b/packages/angular-query/src/__tests__/inject-mutation.test.ts similarity index 62% rename from packages/angular-query-experimental/src/__tests__/inject-mutation.test.ts rename to packages/angular-query/src/__tests__/inject-mutation.test.ts index b54dc3735ea..56c7cff3dc5 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-mutation.test.ts +++ b/packages/angular-query/src/__tests__/inject-mutation.test.ts @@ -1,19 +1,27 @@ import { ApplicationRef, + ChangeDetectionStrategy, Component, - Injector, + ErrorHandler, + effect, input, - provideZonelessChangeDetection, + inputBinding, signal, } from '@angular/core' import { TestBed } from '@angular/core/testing' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { By } from '@angular/platform-browser' import { render } from '@testing-library/angular' import { queryKey, sleep } from '@tanstack/query-test-utils' -import { noop } from '@tanstack/query-core' -import { QueryClient, injectMutation, provideTanStackQuery } from '..' -import { expectSignals, setFixtureSignalInputs } from './test-utils' +import { firstValueFrom } from 'rxjs' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { + QueryClient, + injectIsMutating, + injectMutation, + injectMutationState, + injectQuery, + provideTanStackQuery, +} from '..' +import { expectSignals, provideAngularQueryChangeDetection } from './test-utils' describe('injectMutation', () => { let queryClient: QueryClient @@ -23,8 +31,8 @@ describe('injectMutation', () => { vi.useFakeTimers() TestBed.configureTestingModule({ providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), ], }) }) @@ -33,6 +41,39 @@ describe('injectMutation', () => { vi.useRealTimers() }) + it('publishes mutation failures to observers and cache signals without global reporting', async () => { + vi.useRealTimers() + queryClient.setDefaultOptions({ mutations: { throwOnError: true } }) + const cacheReport = vi.fn() + queryClient.getMutationCache().config.onError = cacheReport + const report = vi.spyOn(TestBed.inject(ErrorHandler), 'handleError') + const error = new Error('mutation failed') + const mutation = TestBed.runInInjectionContext(() => + injectMutation(() => ({ + mutationFn: async () => { + throw error + }, + })), + ) + const count = TestBed.runInInjectionContext(() => injectIsMutating()) + const states = TestBed.runInInjectionContext(() => injectMutationState()) + await TestBed.inject(ApplicationRef).whenStable() + const promise = mutation.mutateAsync() + expect(mutation.status()).toBe('pending') + expect(count()).toBe(1) + expect(states()[0]?.status).toBe('pending') + await expect(promise).rejects.toBe(error) + expect(mutation.error()).toBe(error) + expect(mutation.status()).toBe('error') + expect(count()).toBe(0) + expect(states()[0]?.status).toBe('error') + expect(cacheReport).toHaveBeenCalledTimes(1) + expect(report).not.toHaveBeenCalled() + mutation.mutate() + await TestBed.inject(ApplicationRef).whenStable() + expect(mutation.error()).toBe(error) + }) + it('should be in idle state initially', () => { const mutation = TestBed.runInInjectionContext(() => { return injectMutation(() => ({ @@ -51,110 +92,76 @@ describe('injectMutation', () => { it('should change state after invoking mutate', async () => { const result = 'Mock data' - @Component({ - template: ` -
isIdle: {{ mutation.isIdle() }}
-
isPending: {{ mutation.isPending() }}
-
isError: {{ mutation.isError() }}
-
isSuccess: {{ mutation.isSuccess() }}
-
data: {{ mutation.data() ?? 'none' }}
-
error: {{ mutation.error()?.message ?? 'none' }}
- `, - }) - class Page { - readonly mutation = injectMutation(() => ({ + const mutation = TestBed.runInInjectionContext(() => { + return injectMutation(() => ({ mutationFn: (params: string) => sleep(10).then(() => params), })) - } + }) - const rendered = await render(Page) + TestBed.tick() - rendered.fixture.componentInstance.mutation.mutate(result) + mutation.mutate(result) await vi.advanceTimersByTimeAsync(0) - rendered.fixture.detectChanges() - expect(rendered.getByText('isIdle: false')).toBeInTheDocument() - expect(rendered.getByText('isPending: true')).toBeInTheDocument() - expect(rendered.getByText('isError: false')).toBeInTheDocument() - expect(rendered.getByText('isSuccess: false')).toBeInTheDocument() - expect(rendered.getByText('data: none')).toBeInTheDocument() - expect(rendered.getByText('error: none')).toBeInTheDocument() + expectSignals(mutation, { + isIdle: false, + isPending: true, + isError: false, + isSuccess: false, + data: undefined, + error: null, + }) }) it('should return error when request fails', async () => { - @Component({ - template: ` -
isIdle: {{ mutation.isIdle() }}
-
isPending: {{ mutation.isPending() }}
-
isError: {{ mutation.isError() }}
-
isSuccess: {{ mutation.isSuccess() }}
-
data: {{ mutation.data() ?? 'none' }}
-
error: {{ mutation.error()?.message ?? 'none' }}
- `, - }) - class Page { - readonly mutation = injectMutation(() => ({ + const mutation = TestBed.runInInjectionContext(() => { + return injectMutation(() => ({ mutationFn: () => sleep(10).then(() => Promise.reject(new Error('Some error'))), })) - } - - const rendered = await render(Page) + }) - rendered.fixture.componentInstance.mutation.mutate() + mutation.mutate() await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - expect(rendered.getByText('isIdle: false')).toBeInTheDocument() - expect(rendered.getByText('isPending: false')).toBeInTheDocument() - expect(rendered.getByText('isError: true')).toBeInTheDocument() - expect(rendered.getByText('isSuccess: false')).toBeInTheDocument() - expect(rendered.getByText('data: none')).toBeInTheDocument() - expect(rendered.getByText('error: Some error')).toBeInTheDocument() + expectSignals(mutation, { + isIdle: false, + isPending: false, + isError: true, + isSuccess: false, + data: undefined, + error: Error('Some error'), + }) }) it('should return data when request succeeds', async () => { const result = 'Mock data' - - @Component({ - template: ` -
isIdle: {{ mutation.isIdle() }}
-
isPending: {{ mutation.isPending() }}
-
isError: {{ mutation.isError() }}
-
isSuccess: {{ mutation.isSuccess() }}
-
data: {{ mutation.data() ?? 'none' }}
-
error: {{ mutation.error()?.message ?? 'none' }}
- `, - }) - class Page { - readonly mutation = injectMutation(() => ({ + const mutation = TestBed.runInInjectionContext(() => { + return injectMutation(() => ({ mutationFn: (params: string) => sleep(10).then(() => params), })) - } - - const rendered = await render(Page) + }) - rendered.fixture.componentInstance.mutation.mutate(result) + mutation.mutate(result) await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() - expect(rendered.getByText('isIdle: false')).toBeInTheDocument() - expect(rendered.getByText('isPending: false')).toBeInTheDocument() - expect(rendered.getByText('isError: false')).toBeInTheDocument() - expect(rendered.getByText('isSuccess: true')).toBeInTheDocument() - expect(rendered.getByText(`data: ${result}`)).toBeInTheDocument() - expect(rendered.getByText('error: none')).toBeInTheDocument() + expectSignals(mutation, { + isIdle: false, + isPending: false, + isError: false, + isSuccess: true, + data: result, + error: null, + }) }) - it('should update mutation when reactive options change', () => { + it('reactive options should update mutation', () => { const mutationCache = queryClient.getMutationCache() // Signal will be updated before the mutation is called // this test confirms that the mutation uses the updated value - const key1 = queryKey() - const key2 = queryKey() - const mutationKey = signal(key1) + const mutationKey = signal(['1']) const mutation = TestBed.runInInjectionContext(() => { return injectMutation(() => ({ mutationKey: mutationKey(), @@ -162,54 +169,123 @@ describe('injectMutation', () => { })) }) - mutationKey.set(key2) + mutationKey.set(['2']) mutation.mutate('xyz') - const mutations = mutationCache.find({ mutationKey: key2 }) + const mutations = mutationCache.find({ mutationKey: ['2'] }) - expect(mutations?.options.mutationKey).toEqual(key2) + expect(mutations?.options.mutationKey).toEqual(['2']) }) - it('should reset state after invoking mutation.reset', async () => { - @Component({ - template: ` -
isIdle: {{ mutation.isIdle() }}
-
isPending: {{ mutation.isPending() }}
-
isError: {{ mutation.isError() }}
-
isSuccess: {{ mutation.isSuccess() }}
-
data: {{ mutation.data() ?? 'none' }}
-
error: {{ mutation.error()?.message ?? 'none' }}
- `, - }) - class Page { + it('reflects a mutation started in ngOnInit', async () => { + const statusesInsideOnMutate: Array = [] + + @Component({ template: '' }) + class TestComponent { readonly mutation = injectMutation(() => ({ - mutationFn: () => - sleep(10).then(() => Promise.reject(new Error('Some error'))), + mutationFn: () => sleep(10).then(() => 'done'), + onMutate: () => { + statusesInsideOnMutate.push(this.mutation.status()) + }, })) + + ngOnInit() { + this.mutation.mutate() + } } - const rendered = await render(Page) + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() - rendered.fixture.componentInstance.mutation.mutate() + expect(statusesInsideOnMutate).toEqual(['pending']) + expect(fixture.componentInstance.mutation.status()).toBe('pending') await vi.advanceTimersByTimeAsync(11) - rendered.fixture.detectChanges() + TestBed.tick() + expect(fixture.componentInstance.mutation.status()).toBe('success') + }) + + it('allows cache listeners to read the result while options update', () => { + const mutationKey = signal('one') + const mutation = TestBed.runInInjectionContext(() => + injectMutation(() => ({ + mutationKey: ['reentrant-options', mutationKey()], + mutationFn: () => Promise.resolve(), + })), + ) + + mutation.status() + TestBed.tick() + + const readResult = vi.fn(() => mutation.status()) + const unsubscribe = queryClient.getMutationCache().subscribe((event) => { + // setOptions emits synchronously; this read must not re-enter the signal + // computation that caused the options update. + if (event.type === 'observerOptionsUpdated') readResult() + }) + + mutationKey.set('two') + + expect(() => TestBed.tick()).not.toThrow() + expect(readResult).toHaveBeenCalled() + + unsubscribe() + }) + + it('does not track mutation state when mutating from a reactive context', async () => { + const trigger = signal(false) + const runs = vi.fn() + const mutation = TestBed.runInInjectionContext(() => + injectMutation(() => ({ + mutationFn: () => sleep(10), + })), + ) + + TestBed.runInInjectionContext(() => + effect(() => { + runs() + if (trigger()) mutation.mutate() + }), + ) + TestBed.tick() + expect(runs).toHaveBeenCalledOnce() + + trigger.set(true) + TestBed.tick() + expect(runs).toHaveBeenCalledTimes(2) - expect(rendered.getByText('isError: true')).toBeInTheDocument() - expect(rendered.getByText('error: Some error')).toBeInTheDocument() + await vi.advanceTimersByTimeAsync(11) + TestBed.tick() + expect(runs).toHaveBeenCalledTimes(2) + }) + + it('should reset state after invoking mutation.reset', async () => { + const mutation = TestBed.runInInjectionContext(() => { + return injectMutation(() => ({ + mutationFn: () => + sleep(10).then(() => Promise.reject(new Error('Some error'))), + })) + }) - rendered.fixture.componentInstance.mutation.reset() + mutation.mutate() + + await vi.advanceTimersByTimeAsync(11) + + expect(mutation.isError()).toBe(true) + + mutation.reset() await vi.advanceTimersByTimeAsync(0) - rendered.fixture.detectChanges() - expect(rendered.getByText('isIdle: true')).toBeInTheDocument() - expect(rendered.getByText('isPending: false')).toBeInTheDocument() - expect(rendered.getByText('isError: false')).toBeInTheDocument() - expect(rendered.getByText('isSuccess: false')).toBeInTheDocument() - expect(rendered.getByText('data: none')).toBeInTheDocument() - expect(rendered.getByText('error: none')).toBeInTheDocument() + expectSignals(mutation, { + isIdle: true, + isPending: false, + isError: false, + isSuccess: false, + data: undefined, + error: null, + }) }) describe('side effects', () => { @@ -328,142 +404,6 @@ describe('injectMutation', () => { expect(onSettled).toHaveBeenCalledTimes(1) }) - it('should call onSuccess and onSettled when passed as arguments of mutate function', async () => { - const callbacks: Array = [] - const mutation = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationFn: (params: string) => sleep(10).then(() => params), - })) - }) - - mutation.mutate('', { - onSuccess: () => callbacks.push('mutate.onSuccess'), - onSettled: () => callbacks.push('mutate.onSettled'), - }) - - await vi.advanceTimersByTimeAsync(10) - - expect(callbacks).toEqual(['mutate.onSuccess', 'mutate.onSettled']) - }) - - it('should call onError and onSettled when passed as arguments of mutate function', async () => { - const callbacks: Array = [] - const mutation = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationFn: (_params: string) => - sleep(10).then(() => Promise.reject(new Error('Some error'))), - })) - }) - - mutation.mutate('', { - onError: () => callbacks.push('mutate.onError'), - onSettled: () => callbacks.push('mutate.onSettled'), - }) - - await vi.advanceTimersByTimeAsync(10) - - expect(callbacks).toEqual(['mutate.onError', 'mutate.onSettled']) - }) - - it('should call onSuccess and onSettled when passed as arguments of mutateAsync function', async () => { - const callbacks: Array = [] - const mutation = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationFn: (params: string) => sleep(10).then(() => params), - })) - }) - - mutation.mutateAsync('', { - onSuccess: () => callbacks.push('mutateAsync.onSuccess'), - onSettled: () => callbacks.push('mutateAsync.onSettled'), - }) - - await vi.advanceTimersByTimeAsync(10) - - expect(callbacks).toEqual([ - 'mutateAsync.onSuccess', - 'mutateAsync.onSettled', - ]) - }) - - it('should call onError and onSettled when passed as arguments of mutateAsync function', async () => { - const callbacks: Array = [] - const mutation = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationFn: (_params: string) => - sleep(10).then(() => Promise.reject(new Error('Some error'))), - })) - }) - - mutation - .mutateAsync('', { - onError: () => callbacks.push('mutateAsync.onError'), - onSettled: () => callbacks.push('mutateAsync.onSettled'), - }) - .catch(noop) - - await vi.advanceTimersByTimeAsync(10) - - expect(callbacks).toEqual([ - 'mutateAsync.onError', - 'mutateAsync.onSettled', - ]) - }) - - it('should call onSuccess when passed as an argument of mutateAsync function', async () => { - const callbacks: Array = [] - const mutation = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationFn: (params: string) => sleep(10).then(() => params), - })) - }) - - mutation.mutateAsync('', { - onSuccess: () => callbacks.push('mutateAsync.onSuccess'), - }) - - await vi.advanceTimersByTimeAsync(10) - - expect(callbacks).toEqual(['mutateAsync.onSuccess']) - }) - - it('should call onError when passed as an argument of mutateAsync function', async () => { - const callbacks: Array = [] - const mutation = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationFn: (_params: string) => - sleep(10).then(() => Promise.reject(new Error('Some error'))), - })) - }) - - mutation - .mutateAsync('', { - onError: () => callbacks.push('mutateAsync.onError'), - }) - .catch(noop) - - await vi.advanceTimersByTimeAsync(10) - - expect(callbacks).toEqual(['mutateAsync.onError']) - }) - - it('should call onSettled when passed as an argument of mutateAsync function', async () => { - const callbacks: Array = [] - const mutation = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationFn: (params: string) => sleep(10).then(() => params), - })) - }) - - mutation.mutateAsync('', { - onSettled: () => callbacks.push('mutateAsync.onSettled'), - }) - - await vi.advanceTimersByTimeAsync(10) - - expect(callbacks).toEqual(['mutateAsync.onSettled']) - }) - it('should fire both onSettled functions', async () => { const onSettled = vi.fn() const onSettledOnFunction = vi.fn() @@ -600,6 +540,7 @@ describe('injectMutation', () => { {{ mutation.data() }} `, + changeDetection: ChangeDetectionStrategy.OnPush, }) class FakeComponent { name = input.required() @@ -614,20 +555,24 @@ describe('injectMutation', () => { } } - const fixture = TestBed.createComponent(FakeComponent) - const { debugElement } = fixture - setFixtureSignalInputs(fixture, { name: 'value' }) + const name = signal('value') + const rendered = await render(FakeComponent, { + bindings: [inputBinding('name', name.asReadonly())], + detectChangesOnRender: false, + }) + rendered.fixture.detectChanges() - const button = debugElement.query(By.css('button')) - button.triggerEventHandler('click') + rendered.getByRole('button').click() await vi.advanceTimersByTimeAsync(11) - fixture.detectChanges() + rendered.fixture.detectChanges() - const text = debugElement.query(By.css('span')).nativeElement.textContent - expect(text).toEqual('value') - const mutation = mutationCache.find({ mutationKey: ['fake', 'value'] }) - expect(mutation?.options.mutationKey).toStrictEqual(['fake', 'value']) + expect(rendered.getByText('value')).toBeInTheDocument() + const mutation = mutationCache.find({ + mutationKey: ['fake', 'value'], + }) + expect(mutation).toBeDefined() + expect(mutation!.options.mutationKey).toStrictEqual(['fake', 'value']) }) it('should update options on required signal input change', async () => { @@ -639,6 +584,7 @@ describe('injectMutation', () => { {{ mutation.data() }} `, + changeDetection: ChangeDetectionStrategy.OnPush, }) class FakeComponent { name = input.required() @@ -653,26 +599,27 @@ describe('injectMutation', () => { } } - const fixture = TestBed.createComponent(FakeComponent) - const { debugElement } = fixture - setFixtureSignalInputs(fixture, { name: 'value' }) - - const button = debugElement.query(By.css('button')) - const span = debugElement.query(By.css('span')) + const name = signal('value') + const rendered = await render(FakeComponent, { + bindings: [inputBinding('name', name.asReadonly())], + detectChangesOnRender: false, + }) + rendered.fixture.detectChanges() - button.triggerEventHandler('click') + rendered.getByRole('button').click() await vi.advanceTimersByTimeAsync(11) - fixture.detectChanges() + rendered.fixture.detectChanges() - expect(span.nativeElement.textContent).toEqual('value') + expect(rendered.getByText('value')).toBeInTheDocument() - setFixtureSignalInputs(fixture, { name: 'updatedValue' }) + name.set('updatedValue') + rendered.fixture.detectChanges() - button.triggerEventHandler('click') + rendered.getByRole('button').click() await vi.advanceTimersByTimeAsync(11) - fixture.detectChanges() + rendered.fixture.detectChanges() - expect(span.nativeElement.textContent).toEqual('updatedValue') + expect(rendered.getByText('updatedValue')).toBeInTheDocument() const mutations = mutationCache.findAll() expect(mutations.length).toBe(2) @@ -681,126 +628,14 @@ describe('injectMutation', () => { expect(mutation2!.options.mutationKey).toEqual(['fake', 'updatedValue']) }) - describe('throwOnError', () => { - it('should evaluate throwOnError when mutation is expected to throw', async () => { - const key = queryKey() - const err = new Error('Expected mock error. All is well!') - const boundaryFn = vi.fn() - const { mutate } = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationKey: key, - mutationFn: () => { - return Promise.reject(err) - }, - throwOnError: boundaryFn, - })) - }) - - TestBed.tick() - - mutate() - - await vi.advanceTimersByTimeAsync(0) - - expect(boundaryFn).toHaveBeenCalledTimes(1) - expect(boundaryFn).toHaveBeenCalledWith(err) - }) - - it('should throw when throwOnError is true and mutate is used', async () => { - const key = queryKey() - const { mutate } = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationKey: key, - mutationFn: () => { - return Promise.reject( - new Error('Expected mock error. All is well!'), - ) - }, - throwOnError: true, - })) - }) - - TestBed.tick() - - mutate() - - await expect(vi.advanceTimersByTimeAsync(0)).rejects.toThrow( - 'Expected mock error. All is well!', - ) - }) - }) - - it('should throw when throwOnError is true', async () => { - const key = queryKey() - const err = new Error('Expected mock error. All is well!') - const { mutateAsync } = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationKey: key, - mutationFn: () => { - return Promise.reject(err) - }, - throwOnError: true, - })) - }) - - await expect(() => mutateAsync()).rejects.toThrow(err) - }) - - it('should throw when throwOnError function returns true', async () => { - const key = queryKey() - const err = new Error('Expected mock error. All is well!') - const { mutateAsync } = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationKey: key, - mutationFn: () => { - return Promise.reject(err) - }, - throwOnError: () => true, - })) - }) - - await expect(() => mutateAsync()).rejects.toThrow(err) - }) - - it('should resolve mutateAsync with the value returned from mutationFn', async () => { - const key = queryKey() - const { mutateAsync } = TestBed.runInInjectionContext(() => { - return injectMutation(() => ({ - mutationKey: key, - mutationFn: (params: string) => sleep(10).then(() => params), - })) - }) - - const promise = mutateAsync('Mock data') - await vi.advanceTimersByTimeAsync(10) - - await expect(promise).resolves.toBe('Mock data') - }) - describe('injection context', () => { - it('should throw NG0203 with descriptive error outside injection context', () => { - const key = queryKey() + it('throws NG0203 with descriptive error outside injection context', () => { expect(() => { injectMutation(() => ({ - mutationKey: key, + mutationKey: ['injectionContextError'], mutationFn: () => Promise.resolve(), })) - }).toThrow(/NG0203(.*?)injectMutation/) - }) - - it('should be usable outside injection context when passing an injector', () => { - const key = queryKey() - expect(() => { - injectMutation( - () => ({ - mutationKey: key, - mutationFn: () => Promise.resolve(), - }), - { - injector: TestBed.inject(Injector), - }, - ) - }).not.toThrow() + }).toThrowError(/NG0203(.*?)injectMutation/) }) it('should complete mutation before whenStable() resolves', async () => { @@ -808,10 +643,9 @@ describe('injectMutation', () => { let mutationStarted = false let mutationCompleted = false - const key = queryKey() const mutation = TestBed.runInInjectionContext(() => injectMutation(() => ({ - mutationKey: key, + mutationKey: ['pendingTasksTest'], mutationFn: async (data: string) => { mutationStarted = true await sleep(50) @@ -821,11 +655,9 @@ describe('injectMutation', () => { })), ) - // Initial state expect(mutation.data()).toBeUndefined() expect(mutationStarted).toBe(false) - // Start mutation mutation.mutate('test') // Wait for mutation to start and Angular to be "stable" @@ -841,6 +673,14 @@ describe('injectMutation', () => { }) it('should handle synchronous mutation with retry', async () => { + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + const app = TestBed.inject(ApplicationRef) let attemptCount = 0 @@ -858,7 +698,6 @@ describe('injectMutation', () => { })), ) - // Start mutation mutation.mutate('retry-test') // Synchronize pending effects for each retry attempt @@ -883,14 +722,20 @@ describe('injectMutation', () => { }) it('should handle multiple synchronous mutations on same key', async () => { + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + const app = TestBed.inject(ApplicationRef) let callCount = 0 - const key = queryKey() - const mutation1 = TestBed.runInInjectionContext(() => injectMutation(() => ({ - mutationKey: key, + mutationKey: ['sync-mutation-key'], mutationFn: async (data: string) => { callCount++ return `mutation1: ${data}` @@ -900,7 +745,7 @@ describe('injectMutation', () => { const mutation2 = TestBed.runInInjectionContext(() => injectMutation(() => ({ - mutationKey: key, + mutationKey: ['sync-mutation-key'], mutationFn: async (data: string) => { callCount++ return `mutation2: ${data}` @@ -908,7 +753,6 @@ describe('injectMutation', () => { })), ) - // Start both mutations mutation1.mutate('test1') mutation2.mutate('test2') @@ -929,22 +773,40 @@ describe('injectMutation', () => { }) it('should handle synchronous mutation with optimistic updates', async () => { + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + const app = TestBed.inject(ApplicationRef) - const testQueryKey = queryKey() + const testQueryKey = ['sync-optimistic'] let onMutateCalled = false let onSuccessCalled = false + let queryDataInsideOnMutate: string | undefined - // Set initial data queryClient.setQueryData(testQueryKey, 'initial') + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: testQueryKey, + queryFn: () => Promise.resolve('initial'), + staleTime: Infinity, + })), + ) + const mutation = TestBed.runInInjectionContext(() => injectMutation(() => ({ - mutationFn: async (data: string) => `final: ${data}`, // Synchronous resolution + mutationFn: async (data: string) => { + await sleep(50) + return `final: ${data}` + }, onMutate: async (variables) => { onMutateCalled = true - const previousData = queryClient.getQueryData(testQueryKey) queryClient.setQueryData(testQueryKey, `optimistic: ${variables}`) - return { previousData } + queryDataInsideOnMutate = query.data() }, onSuccess: (data) => { onSuccessCalled = true @@ -953,37 +815,84 @@ describe('injectMutation', () => { })), ) - // Start mutation - mutation.mutate('test') - - // Synchronize pending effects TestBed.tick() - const stablePromise = app.whenStable() + expect(queryClient.getQueryData(testQueryKey)).toBe('initial') + mutation.mutate('test') + // Flush microtasks to allow TanStack Query's scheduled notifications to process await Promise.resolve() - await vi.advanceTimersByTimeAsync(1) - await stablePromise + // The observed query signal must be current inside the onMutate callback, + // immediately after the optimistic cache write. expect(onMutateCalled).toBe(true) + expect(queryClient.getQueryData(testQueryKey)).toBe('optimistic: test') + expect(queryDataInsideOnMutate).toBe('optimistic: test') + + // Check stability before the mutation completes, waiting for the next macro task + await vi.advanceTimersByTimeAsync(0) + expect(mutation.isPending()).toBe(true) + expect(await firstValueFrom(app.isStable)).toBe(false) + + // Wait for the mutation to complete + const stablePromise = app.whenStable() + await vi.advanceTimersByTimeAsync(60) + await stablePromise + expect(onSuccessCalled).toBe(true) expect(mutation.isSuccess()).toBe(true) expect(mutation.data()).toBe('final: test') expect(queryClient.getQueryData(testQueryKey)).toBe('final: test') }) + it('reads an optimistic update inside onMutate before the query signal or effects initialize', async () => { + const testQueryKey = ['unread-sync-optimistic'] + const seenInsideOnMutate: Array = [] + queryClient.setQueryData(testQueryKey, 'initial') + + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: testQueryKey, + queryFn: () => Promise.resolve('initial'), + staleTime: Infinity, + })), + ) + const mutation = TestBed.runInInjectionContext(() => + injectMutation(() => ({ + mutationFn: async () => 'server', + onMutate: () => { + queryClient.setQueryData(testQueryKey, 'optimistic') + seenInsideOnMutate.push(query.data()) + }, + })), + ) + + // No signal read and no TestBed.tick() occurs before mutateAsync. The + // first query read must still pull the optimistic cache value; its + // observer subscription can be committed later. + await mutation.mutateAsync() + + expect(seenInsideOnMutate).toEqual(['optimistic']) + }) + it('should handle synchronous mutation cancellation', async () => { + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + const app = TestBed.inject(ApplicationRef) - const key = queryKey() const mutation = TestBed.runInInjectionContext(() => injectMutation(() => ({ - mutationKey: key, + mutationKey: ['cancel-sync'], mutationFn: async (data: string) => `processed: ${data}`, // Synchronous resolution })), ) - // Start mutation mutation.mutate('test') // Synchronize pending effects diff --git a/packages/angular-query/src/__tests__/inject-queries.test-d.ts b/packages/angular-query/src/__tests__/inject-queries.test-d.ts new file mode 100644 index 00000000000..7be6f773913 --- /dev/null +++ b/packages/angular-query/src/__tests__/inject-queries.test-d.ts @@ -0,0 +1,307 @@ +import { describe, expectTypeOf, it } from 'vitest' +import { injectQueries, skipToken, toResource } from '..' +import { queryOptions } from '../query-options' +import type { CreateQueryOptions, CreateQueryResult, OmitKeyof } from '..' +import type { Resource, Signal } from '@angular/core' + +describe('InjectQueries config object overload', () => { + it('infers tagged custom errors in parallel queries and combine', () => { + class CustomError extends Error { + detail = 'detail' + } + const options = queryOptions({ + queryKey: ['tagged'], + queryFn: () => 1, + }) + const queries = injectQueries(() => ({ queries: [options] })) + expectTypeOf(queries()[0].error()).toEqualTypeOf() + expectTypeOf(queries()[0].data()).toEqualTypeOf() + const combined = injectQueries(() => ({ + queries: [options], + combine: (results) => results[0].error, + })) + expectTypeOf(combined()).toEqualTypeOf() + }) + it('preserves custom errors from annotated options without a query-key tag', () => { + class CustomError extends Error { + detail = 'detail' + } + const options: CreateQueryOptions = { + queryKey: ['annotated'], + queryFn: () => 1, + } + const queries = injectQueries(() => ({ queries: [options] })) + expectTypeOf(queries()[0].error()).toEqualTypeOf() + expectTypeOf(queries()[0].data()).toEqualTypeOf() + const combined = injectQueries(() => ({ + queries: [options], + combine: (results) => results[0].error, + })) + expectTypeOf(combined()).toEqualTypeOf() + }) + + it('should expose Angular resource views', () => { + const queryResults = injectQueries(() => ({ + queries: [ + { + queryKey: ['key'], + queryFn: () => Promise.resolve('data'), + }, + ], + })) + + expectTypeOf(toResource(queryResults()[0])).toMatchTypeOf< + Resource + >() + + // @ts-expect-error Resources are created explicitly with toResource. + queryResults()[0].resource + }) + + it('TData should always be defined when initialData is provided as an object', () => { + const query1 = { + queryKey: ['key1'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: false, + }, + } + + const query2 = { + queryKey: ['key2'], + queryFn: () => 'Query Data', + initialData: 'initial data', + } + + const query3 = { + queryKey: ['key2'], + queryFn: () => 'Query Data', + } + + const queryResults = injectQueries(() => ({ + queries: [query1, query2, query3], + })) + + const query1Data = queryResults()[0].data() + const query2Data = queryResults()[1].data() + const query3Data = queryResults()[2].data() + + expectTypeOf(query1Data).toEqualTypeOf<{ wow: boolean }>() + expectTypeOf(query2Data).toEqualTypeOf() + expectTypeOf(query3Data).toEqualTypeOf() + }) + + it('TData should be defined when passed through queryOptions', () => { + const options = queryOptions({ + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + const queryResults = injectQueries(() => ({ queries: [options] })) + + const data = queryResults()[0].data() + + expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>() + }) + + it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into injectQuery', () => { + const query1 = queryOptions({ + queryKey: ['key'], + queryFn: () => Promise.resolve(1), + select: (data) => data > 1, + }) + + const query2 = { + queryKey: ['key'], + queryFn: () => Promise.resolve(1), + select: (data: number) => data > 1, + } + + const queryResults = injectQueries(() => ({ queries: [query1, query2] })) + const query1Data = queryResults()[0].data() + const query2Data = queryResults()[1].data() + + expectTypeOf(query1Data).toEqualTypeOf() + expectTypeOf(query2Data).toEqualTypeOf() + }) + + it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { + const queryResults = injectQueries(() => ({ + queries: [ + { + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => undefined as { wow: boolean } | undefined, + }, + ], + })) + + const data = queryResults()[0].data() + + expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>() + }) + + describe('custom injectable', () => { + it('should allow custom hooks using UseQueryOptions', () => { + type Data = string + + const injectCustomQueries = ( + options?: OmitKeyof, 'queryKey' | 'queryFn'>, + ) => { + return injectQueries(() => ({ + queries: [ + { + ...options, + queryKey: ['todos-key'], + queryFn: () => Promise.resolve('data'), + }, + ], + })) + } + + const queryResults = injectCustomQueries() + const data = queryResults()[0].data() + + expectTypeOf(data).toEqualTypeOf() + }) + }) + + it('TData should have correct type when conditional skipToken is passed', () => { + const queryResults = injectQueries(() => ({ + queries: [ + { + queryKey: ['withSkipToken'], + queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), + }, + ], + })) + + const firstResult = queryResults()[0] + + expectTypeOf(firstResult).toEqualTypeOf>() + expectTypeOf(firstResult.data()).toEqualTypeOf() + }) + + it('should return correct data for dynamic queries with mixed result types', () => { + const Queries1 = { + get: () => + queryOptions({ + queryKey: ['key1'], + queryFn: () => Promise.resolve(1), + }), + } + const Queries2 = { + get: () => + queryOptions({ + queryKey: ['key2'], + queryFn: () => Promise.resolve(true), + }), + } + + const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() })) + const result = injectQueries(() => ({ + queries: [...queries1List, { ...Queries2.get() }], + })) + + expectTypeOf(result).toBeFunction() + }) +}) + +describe('InjectQueries combine', () => { + it('should provide the correct type for the combine function', () => { + injectQueries(() => ({ + queries: [ + { + queryKey: ['key'], + queryFn: () => Promise.resolve(1), + }, + { + queryKey: ['key2'], + queryFn: () => Promise.resolve(true), + }, + ], + combine: (results) => { + expectTypeOf(results[0].data).toEqualTypeOf() + expectTypeOf(results[0].refetch).toBeCallableWith() + expectTypeOf(results[1].data).toEqualTypeOf() + expectTypeOf(results[1].refetch).toBeCallableWith() + }, + })) + }) + + it('should provide the correct types on the combined result with initial data', () => { + injectQueries(() => ({ + queries: [ + { + queryKey: ['key'], + queryFn: () => Promise.resolve(1), + initialData: 1, + }, + ], + combine: (results) => { + expectTypeOf(results[0].data).toEqualTypeOf() + expectTypeOf(results[0].refetch).toBeCallableWith() + }, + })) + }) + + it('should provide the correct result type', () => { + const queryResults = injectQueries(() => ({ + queries: [ + { + queryKey: ['key'], + queryFn: () => Promise.resolve(1), + }, + { + queryKey: ['key2'], + queryFn: () => Promise.resolve(true), + }, + ], + combine: (results) => ({ + data: { + 1: results[0].data, + 2: results[1].data, + }, + fn: () => {}, + }), + })) + + expectTypeOf(queryResults).branded.toEqualTypeOf< + Signal<{ + data: { + 1: number | undefined + 2: boolean | undefined + } + fn: () => void + }> + >() + }) + + it('should provide the correct types on the result with initial data', () => { + const queryResults = injectQueries(() => ({ + queries: [ + { + queryKey: ['key'], + queryFn: () => Promise.resolve(1), + initialData: 1, + }, + ], + })) + + expectTypeOf(queryResults()[0].data()).toEqualTypeOf() + }) +}) diff --git a/packages/angular-query/src/__tests__/inject-queries.test.ts b/packages/angular-query/src/__tests__/inject-queries.test.ts new file mode 100644 index 00000000000..10cde4532d6 --- /dev/null +++ b/packages/angular-query/src/__tests__/inject-queries.test.ts @@ -0,0 +1,1615 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { render } from '@testing-library/angular' +import { + ApplicationRef, + ChangeDetectionStrategy, + Component, + ErrorHandler, + computed, + effect, + input, + inputBinding, + signal, +} from '@angular/core' +import { TestBed } from '@angular/core/testing' +import { queryKey, sleep } from '@tanstack/query-test-utils' +import { provideIsRestoring } from '../internal' +import { QueryClient, onlineManager, provideTanStackQuery, skipToken } from '..' +import { injectQueries } from '../inject-queries' +import { + provideAngularQueryChangeDetection, + setupTanStackQueryTestBed, +} from './test-utils' + +// cspell:ignore ZONEFUL + +let queryClient: QueryClient + +beforeEach(() => { + vi.useFakeTimers() + queryClient = new QueryClient() + vi.useFakeTimers({ shouldAdvanceTime: true }) + setupTanStackQueryTestBed(queryClient) +}) + +afterEach(() => { + onlineManager.setOnline(true) + vi.useRealTimers() +}) + +describe('injectQueries', () => { + it.each([false, true])( + 'uses current options and slot identity for multi-query refetch (combine=%s)', + async (combine) => { + vi.useRealTimers() + const keys = signal(['a', 'b']) + const version = signal('old') + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => { + const current = version() + return { + queries: keys().map((key) => ({ + queryKey: [key], + enabled: false, + queryFn: async () => `${key}:${current}`, + })), + combine: combine ? (results) => results : undefined, + } + }), + ) + const refetch = queries()[0]!.refetch + version.set('new') + expect((await refetch()).data).toBe('a:new') + keys.set(['b', 'a']) + expect((await refetch()).data).toBe('b:new') + keys.set([]) + expect(queries()).toHaveLength(0) + await expect(refetch()).rejects.toThrow('removed query at index 0') + keys.set(['a']) + const restoredRefetch = queries()[0]!.refetch + expect(restoredRefetch).not.toBe(refetch) + expect((await restoredRefetch()).data).toBe('a:new') + }, + ) + + it('should keep failed refetch state and cached data readable without global reporting', async () => { + vi.useRealTimers() + queryClient.setDefaultOptions({ + queries: { retry: false, throwOnError: true }, + }) + const report = vi.spyOn(TestBed.inject(ErrorHandler), 'handleError') + const error = new Error('query failed') + const options = { + queryKey: ['error'], + initialData: 'cached', + enabled: false, + queryFn: async (): Promise => { + throw error + }, + } + const query = TestBed.runInInjectionContext( + () => injectQueries(() => ({ queries: [options] }))()[0], + ) + await TestBed.inject(ApplicationRef).whenStable() + await expect(query.refetch()).resolves.toMatchObject({ + status: 'error', + error, + }) + expect(query.error()).toBe(error) + expect(query.data()).toBe('cached') + expect(query.isError()).toBe(true) + await expect(query.refetch({ throwOnError: true })).rejects.toBe(error) + expect(report).not.toHaveBeenCalled() + }) + + it('throws NG0203 with descriptive error outside injection context', () => { + expect(() => { + injectQueries(() => ({ + queries: [ + { + queryKey: ['injectionContextError'], + queryFn: () => Promise.resolve(1), + }, + ], + })) + }).toThrowError(/NG0203(.*?)injectQueries/) + }) + + it('allows cache listeners to read a result while options update', () => { + const staleTime = signal(0) + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [ + { + queryKey: ['reentrant-options'], + queryFn: () => 'data', + enabled: false, + staleTime: staleTime(), + }, + ], + })), + ) + + TestBed.tick() + const query = queries()[0] + const readResult = vi.fn(() => query.status()) + const subscriptionEvents: Array = [] + const unsubscribe = queryClient.getQueryCache().subscribe((event) => { + // setQueries emits synchronously; this read must not re-enter the signal + // computation that caused the options update. + if (event.type === 'observerOptionsUpdated') readResult() + if (event.type === 'observerAdded' || event.type === 'observerRemoved') { + subscriptionEvents.push(event.type) + } + }) + + staleTime.set(1) + + expect(() => TestBed.tick()).not.toThrow() + expect(readResult).toHaveBeenCalled() + expect(subscriptionEvents).toEqual([]) + + unsubscribe() + }) + + it('allows deferred cache-listener reads during restoration detach and reattach', async () => { + const isRestoring = signal(false) + setupTanStackQueryTestBed(queryClient, { + providers: [provideIsRestoring(() => isRestoring.asReadonly())], + }) + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [ + { + queryKey: ['reentrant-restoration-subscription'], + queryFn: () => 'data', + enabled: false, + }, + ], + })), + ) + expect(queries()[0].status()).toBe('pending') + TestBed.tick() + + const nestedStatuses: Array = [] + const unsubscribe = queryClient.getQueryCache().subscribe((event) => { + if (event.type === 'observerAdded' || event.type === 'observerRemoved') { + void Promise.resolve().then(() => + nestedStatuses.push(queries()[0].status()), + ) + } + }) + + isRestoring.set(true) + expect(() => TestBed.tick()).not.toThrow() + isRestoring.set(false) + expect(() => TestBed.tick()).not.toThrow() + + await Promise.resolve() + expect(nestedStatuses).toEqual(['pending', 'pending']) + unsubscribe() + }) + + it('allows deferred cache-listener reads while a list change creates a query', async () => { + const key = signal('old') + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [ + { + queryKey: ['reentrant-query-added', key()], + queryFn: () => 'data', + enabled: false, + }, + ], + })), + ) + + expect(queries()[0].status()).toBe('pending') + TestBed.tick() + const nestedStatuses: Array = [] + const unsubscribe = queryClient.getQueryCache().subscribe((event) => { + if (event.type === 'added') + void Promise.resolve().then(() => + nestedStatuses.push(queries()[0].status()), + ) + }) + + key.set('new') + + expect(() => queries()[0].status()).not.toThrow() + expect(nestedStatuses).toEqual([]) + expect(() => TestBed.tick()).not.toThrow() + await Promise.resolve() + expect(nestedStatuses).toEqual(['pending']) + unsubscribe() + }) + + it('should return the correct states', async () => { + const key1 = queryKey() + const key2 = queryKey() + const results: Array>> = [] + + @Component({ + template: ` +
+
+ data1: {{ queries()[0].data() ?? 'null' }}, data2: + {{ queries()[1].data() ?? 'null' }} +
+
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + toString(val: any) { + return String(val) + } + queries = injectQueries(() => ({ + queries: [ + { + queryKey: key1, + queryFn: () => sleep(10).then(() => 1), + }, + { + queryKey: key2, + queryFn: () => sleep(100).then(() => 2), + }, + ], + })) + + _pushResults = effect(() => { + const snapshot = this.queries().map((q) => ({ data: q.data() })) + results.push(snapshot) + }) + } + + const rendered = await render(Page, { + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + + await vi.advanceTimersByTimeAsync(10) + rendered.fixture.detectChanges() + + expect(results.some((snapshot) => snapshot[0]?.data === 1)).toBe(true) + + await vi.advanceTimersByTimeAsync(91) + rendered.fixture.detectChanges() + + expect(rendered.getByText('data1: 1, data2: 2')).toBeInTheDocument() + + expect( + results.some( + (snapshot) => + snapshot.length === 2 && + snapshot[0]?.data === undefined && + snapshot[1]?.data === undefined, + ), + ).toBe(true) + expect( + results.some( + (snapshot) => + snapshot.length === 2 && + snapshot[0]?.data === 1 && + snapshot[1]?.data === undefined, + ), + ).toBe(true) + expect( + results.some( + (snapshot) => + snapshot.length === 2 && + snapshot[0]?.data === 1 && + snapshot[1]?.data === 2, + ), + ).toBe(true) + }) + + it('should update a result field first read after an earlier update', async () => { + let count = 0 + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['late-field-tracking'], + queryFn: async () => { + await sleep(10) + return ++count + }, + }, + ], + })) + } + + const rendered = await render(Page) + rendered.fixture.autoDetectChanges() + const query = rendered.fixture.componentInstance.queries()[0] + + // Only status is read before the first observer update. + expect(query.status()).toBe('pending') + + await vi.advanceTimersByTimeAsync(11) + expect(query.status()).toBe('success') + + // Data starts being observed after the result signal already contains a + // subscription update. It must still participate in future notifications. + expect(query.data()).toBe(1) + + const refetch = query.refetch() + await vi.advanceTimersByTimeAsync(11) + await refetch + + expect(query.data()).toBe(2) + }) + + it('should support combining results', async () => { + const key1 = queryKey() + const key2 = queryKey() + let count = 0 + + const results: Array<{ data: string; refetch: () => void }> = [] + + @Component({ + template: `
data: {{ queries().data }}
`, + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: key1, + queryFn: async () => { + await new Promise((r) => setTimeout(r, 10)) + count++ + return count + }, + }, + { + queryKey: key2, + queryFn: async () => { + await new Promise((r) => setTimeout(r, 100)) + count++ + return count + }, + }, + ], + combine: (queryResults) => { + return { + refetch: () => queryResults.forEach((r) => r.refetch()), + data: queryResults.map((r) => r.data).join(','), + } + }, + })) + + _pushResults = effect(() => { + results.push(this.queries()) + }) + } + + const rendered = await render(Page) + const instance = rendered.fixture.componentInstance + await rendered.findByText('data: 1,2') + expect(instance.queries().data).toBe('1,2') + + instance.queries().refetch() + + await rendered.findByText('data: 3,4') + expect(instance.queries().data).toBe('3,4') + + const dataChanges = results.filter( + (result, index) => result.data !== results[index - 1]?.data, + ) + expect(dataChanges.map((result) => result.data)).toEqual([ + ',', + '1,', + '1,2', + '3,2', + '3,4', + ]) + expect( + results.every((result) => typeof result.refetch === 'function'), + ).toBe(true) + }) + + it('updates the result shape when combine configuration changes', () => { + const shouldCombine = signal(false) + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [ + { + queryKey: ['committed-combine'], + enabled: false, + }, + ], + combine: shouldCombine() + ? (results: Array) => ({ count: results.length }) + : undefined, + })), + ) + + expect(Array.isArray(queries())).toBe(true) + TestBed.tick() + + shouldCombine.set(true) + expect(queries()).toEqual({ count: 1 }) + }) + + it('removes a combined result when combine configuration changes', () => { + const shouldCombine = signal(true) + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [ + { + queryKey: ['committed-combine-removal'], + enabled: false, + }, + ], + combine: shouldCombine() + ? (results: Array) => ({ count: results.length }) + : undefined, + })), + ) + + expect(queries()).toEqual({ count: 1 }) + TestBed.tick() + + shouldCombine.set(false) + expect(Array.isArray(queries())).toBe(true) + expect(queries()).toHaveLength(1) + }) + + it('combines fresh raw results when a signal changes what combine selects', () => { + const showData = signal(false) + const key = ['reactive-combine-selection'] + queryClient.setQueryData(key, 1) + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [{ queryKey: key, enabled: false }], + combine: (results) => ({ value: showData() ? results[0].data : 0 }), + })), + ) + + expect(queries()).toEqual({ value: 0 }) + TestBed.tick() + queryClient.setQueryData(key, 2) + const previous = queries() + queryClient.setQueryData(key, 3) + expect(queries()).toEqual(previous) + expect(queries()).not.toBe(previous) + showData.set(true) + expect(queries()).toEqual({ value: 3 }) + }) + + it('should handle mixed success and error query states', async () => { + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['mixed-error'], + retry: false, + queryFn: async () => { + await new Promise((resolve) => setTimeout(resolve, 10)) + throw new Error('mixed-error') + }, + }, + { + queryKey: ['mixed-success'], + queryFn: async () => { + await new Promise((resolve) => setTimeout(resolve, 20)) + return 'mixed-success' + }, + }, + ], + })) + } + + const rendered = await render(Page) + await vi.advanceTimersByTimeAsync(25) + await Promise.resolve() + + const [errorQuery, successQuery] = + rendered.fixture.componentInstance.queries() + expect(errorQuery.status()).toBe('error') + expect(errorQuery.error()?.message).toBe('mixed-error') + expect(successQuery.status()).toBe('success') + expect(successQuery.data()).toBe('mixed-success') + }) + + it('should cleanup pending tasks when component with active queries is destroyed', async () => { + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['destroy-query-1'], + queryFn: async () => { + await sleep(100) + return 'one' + }, + }, + { + queryKey: ['destroy-query-2'], + queryFn: async () => { + await sleep(100) + return 'two' + }, + }, + ], + })) + } + + // Use a fixture here on purpose: we need component teardown + whenStable() semantics. + const fixture = TestBed.createComponent(Page) + fixture.detectChanges() + expect(fixture.isStable()).toBe(false) + + fixture.destroy() + + const stablePromise = fixture.whenStable() + await vi.advanceTimersByTimeAsync(150) + await stablePromise + + expect(fixture.isStable()).toBe(true) + }) + + it('should react to enabled signal changes', async () => { + const enabled = signal(false) + const fetchSpy = vi.fn(() => sleep(10).then(() => 'enabled-data')) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + enabled = enabled + fetchSpy = fetchSpy + + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['enabled', this.enabled()], + queryFn: this.fetchSpy, + enabled: this.enabled(), + }, + ], + })) + } + + const rendered = await render(Page) + const query = rendered.fixture.componentInstance.queries()[0] + + expect(fetchSpy).not.toHaveBeenCalled() + expect(query.status()).toBe('pending') + + enabled.set(true) + rendered.fixture.detectChanges() + await vi.advanceTimersByTimeAsync(11) + await Promise.resolve() + + expect(fetchSpy).toHaveBeenCalledTimes(1) + expect(query.status()).toBe('success') + expect(query.data()).toBe('enabled-data') + }) + + it('should not resubscribe or refetch unchanged stale queries when options change', async () => { + const multiplier = signal(1) + const fetchSpy = vi.fn(() => sleep(10).then(() => 2)) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => { + const currentMultiplier = multiplier() + + return { + queries: [ + { + queryKey: ['reactive-select'], + queryFn: fetchSpy, + select: (data: number) => data * currentMultiplier, + staleTime: 0, + }, + ], + } + }) + } + + const rendered = await render(Page) + await vi.advanceTimersByTimeAsync(11) + + const query = rendered.fixture.componentInstance.queries()[0] + const cachedQuery = queryClient + .getQueryCache() + .find({ queryKey: ['reactive-select'] })! + + expect(query.data()).toBe(2) + expect(fetchSpy).toHaveBeenCalledTimes(1) + expect(cachedQuery.getObserversCount()).toBe(1) + + multiplier.set(2) + rendered.fixture.detectChanges() + await vi.advanceTimersByTimeAsync(0) + + expect(query.data()).toBe(4) + expect(fetchSpy).toHaveBeenCalledTimes(1) + expect(cachedQuery.getObserversCount()).toBe(1) + + rendered.fixture.destroy() + expect(cachedQuery.getObserversCount()).toBe(0) + }) + + it('should refetch only changed keys when queries length stays the same', async () => { + const ids = signal<[string, string]>(['a', 'b']) + const firstSpy = vi.fn((context: any) => + sleep(10).then(() => `first-${context.queryKey[1]}`), + ) + const secondSpy = vi.fn((context: any) => + sleep(10).then(() => `second-${context.queryKey[1]}`), + ) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + ids = ids + firstSpy = firstSpy + secondSpy = secondSpy + + queries = injectQueries(() => ({ + queries: [ + { + staleTime: Number.POSITIVE_INFINITY, + queryKey: ['first', this.ids()[0]], + queryFn: this.firstSpy, + }, + { + staleTime: Number.POSITIVE_INFINITY, + queryKey: ['second', this.ids()[1]], + queryFn: this.secondSpy, + }, + ], + })) + } + + const rendered = await render(Page) + await vi.advanceTimersByTimeAsync(11) + await Promise.resolve() + + let [firstQuery, secondQuery] = rendered.fixture.componentInstance.queries() + expect(firstQuery.data()).toBe('first-a') + expect(secondQuery.data()).toBe('second-b') + expect(firstSpy).toHaveBeenCalledTimes(1) + expect(secondSpy).toHaveBeenCalledTimes(1) + + ids.set(['c', 'b']) + rendered.fixture.detectChanges() + await vi.advanceTimersByTimeAsync(11) + await Promise.resolve() + ;[firstQuery, secondQuery] = rendered.fixture.componentInstance.queries() + expect(firstQuery.data()).toBe('first-c') + expect(secondQuery.data()).toBe('second-b') + expect(firstSpy).toHaveBeenCalledTimes(2) + expect(secondSpy).toHaveBeenCalledTimes(1) + }) + + it('should retain result proxy and field signal identities across updates', async () => { + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['proxy-cache-update'], + queryFn: () => Promise.resolve('initial'), + }, + ], + })) + } + + const rendered = await render(Page) + await vi.advanceTimersByTimeAsync(0) + + const initialQuery = rendered.fixture.componentInstance.queries()[0] + const initialDataSignal = initialQuery.data + + queryClient.setQueryData(['proxy-cache-update'], 'updated') + await vi.advanceTimersByTimeAsync(0) + + const updatedQuery = rendered.fixture.componentInstance.queries()[0] + expect(updatedQuery).toBe(initialQuery) + expect(updatedQuery.data).toBe(initialDataSignal) + expect(updatedQuery.data()).toBe('updated') + }) + + it('should cache result proxies by index as the queries array changes', async () => { + const queryIds = signal(['a', 'b']) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + ids = queryIds + + queries = injectQueries(() => ({ + queries: this.ids().map((id) => ({ + queryKey: ['proxy-cache-list', id], + queryFn: () => Promise.resolve(id), + staleTime: Number.POSITIVE_INFINITY, + })), + })) + } + + const rendered = await render(Page) + await vi.advanceTimersByTimeAsync(0) + + const instance = rendered.fixture.componentInstance + const initialQueries = instance.queries() + const firstQuery = initialQueries[0] + const secondQuery = initialQueries[1] + + queryIds.set(['a', 'b', 'c']) + rendered.fixture.detectChanges() + await vi.advanceTimersByTimeAsync(0) + + const appendedQueries = instance.queries() + expect(appendedQueries).toHaveLength(3) + expect(appendedQueries[0]).toBe(firstQuery) + expect(appendedQueries[1]).toBe(secondQuery) + expect(appendedQueries[2]).not.toBe(firstQuery) + + queryIds.set(['a']) + rendered.fixture.detectChanges() + await vi.advanceTimersByTimeAsync(0) + + const removedQueries = instance.queries() + expect(removedQueries).toHaveLength(1) + expect(removedQueries[0]).toBe(firstQuery) + + queryIds.set(['a', 'd']) + rendered.fixture.detectChanges() + await vi.advanceTimersByTimeAsync(0) + + const queriesAfterAddingAgain = instance.queries() + expect(queriesAfterAddingAgain[0]).toBe(firstQuery) + expect(queriesAfterAddingAgain[1]).not.toBe(secondQuery) + + queryIds.set(['d', 'a']) + rendered.fixture.detectChanges() + await vi.advanceTimersByTimeAsync(0) + + const reorderedQueries = instance.queries() + expect(reorderedQueries[0]).toBe(firstQuery) + expect(reorderedQueries[1]).not.toBe(secondQuery) + expect(reorderedQueries[0]!.data()).toBe('d') + expect(reorderedQueries[1]!.data()).toBe('a') + }) + + it('should support changes on the queries array', async () => { + const results: Array>> = [] + + @Component({ + template: `
data: {{ mapped() }}
`, + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: queries().map((q) => ({ + queryKey: ['query', q], + queryFn: async () => { + await new Promise((resolve) => setTimeout(resolve, 20 * q)) + return q + }, + })), + })) + + mapped = computed(() => { + const queryData = this.queries().map((q) => q.data()) + if (queryData.length === 0) return 'empty' + return queryData.join(',') + }) + + _pushResults = effect(() => { + const snapshot = this.queries().map((q) => ({ data: q.data() })) + results.push(snapshot) + }) + } + + const queries = signal([1, 2, 4]) + + const rendered = await render(Page) + rendered.fixture.autoDetectChanges() + const instance = rendered.fixture.componentInstance + + await vi.advanceTimersByTimeAsync(20) + rendered.fixture.detectChanges() + await vi.advanceTimersByTimeAsync(20) + rendered.fixture.detectChanges() + await vi.advanceTimersByTimeAsync(40) + rendered.fixture.detectChanges() + await rendered.findByText('data: 1,2,4') + expect(instance.mapped()).toBe('1,2,4') + + const hasSnapshot = (expected: Array): boolean => + results.some( + (snapshot) => + snapshot.length === expected.length && + expected.every((data, index) => snapshot[index]?.data === data), + ) + expect(hasSnapshot([undefined, undefined, undefined])).toBe(true) + expect(hasSnapshot([1, undefined, undefined])).toBe(true) + expect(hasSnapshot([1, 2, undefined])).toBe(true) + expect(hasSnapshot([1, 2, 4])).toBe(true) + + queries.set([3, 4]) + rendered.fixture.detectChanges() + expect(instance.queries()[0]!.data()).toBeUndefined() + expect(instance.queries()[1]!.data()).toBe(4) + expect(instance.mapped()).toBe(',4') + await rendered.findByText('data: 3,4') + expect(instance.mapped()).toBe('3,4') + + expect(results[results.length - 1]).toMatchObject([ + { data: 3 }, + { data: 4 }, + ]) + + queries.set([]) + await rendered.findByText('data: empty') + expect(instance.mapped()).toBe('empty') + + expect(results[results.length - 1]).toMatchObject([]) + }) + + it('should change the rendered component when the queries array changes', async () => { + const userIds = signal([1, 2]) + + @Component({ + template: ` +
    + @for (query of queries(); track $index) { + @if (query.data(); as data) { +
  • {{ data.value }}
  • + } + } +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + userIds = userIds + + queries = injectQueries(() => ({ + queries: this.userIds().map((id) => ({ + queryKey: ['user', id], + queryFn: async () => { + await new Promise((resolve) => setTimeout(resolve, 20)) + return { value: String(id) } + }, + })), + })) + } + + const rendered = await render(Page) + + await rendered.findByText('1') + await rendered.findByText('2') + + userIds.set([3]) + rendered.fixture.detectChanges() + + await rendered.findByText('3') + expect(rendered.queryByText('1')).toBeNull() + expect(rendered.queryByText('2')).toBeNull() + }) + + it('should support required signal inputs', async () => { + @Component({ + selector: 'app-fake', + template: `{{ queries()[0].data() }}`, + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class FakeComponent { + name = input.required() + + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['fake', this.name()], + queryFn: () => this.name(), + }, + ], + })) + } + + const name = signal('signal-input-required-test') + const rendered = await render(FakeComponent, { + bindings: [inputBinding('name', name.asReadonly())], + detectChangesOnRender: false, + }) + rendered.fixture.autoDetectChanges() + rendered.fixture.detectChanges() + await vi.advanceTimersByTimeAsync(0) + + const result = rendered.fixture.nativeElement.textContent + expect(result).toEqual('signal-input-required-test') + }) + + it('should allow reading query state in ngOnInit with required signal inputs', async () => { + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + name = input.required() + initialStatus!: string + + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['queries-ng-on-init', this.name()], + queryFn: () => this.name(), + }, + ], + })) + + ngOnInit() { + this.initialStatus = this.queries()[0].status() + } + } + + const name = signal('queries-ng-on-init') + const rendered = await render(Page, { + bindings: [inputBinding('name', name.asReadonly())], + detectChangesOnRender: false, + }) + + rendered.fixture.detectChanges() + + expect(rendered.fixture.componentInstance.initialStatus).toBe('pending') + + await vi.advanceTimersByTimeAsync(0) + expect(rendered.fixture.componentInstance.queries()[0].data()).toBe( + 'queries-ng-on-init', + ) + }) + + describe('pending tasks', () => { + it('should handle synchronous success and error before whenStable resolves', async () => { + const app = TestBed.inject(ApplicationRef) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['queries-sync-success'], + queryFn: () => 'instant-data', + }, + { + queryKey: ['queries-sync-error'], + queryFn: () => { + throw new Error('instant-error') + }, + retry: false, + }, + ], + })) + } + + const fixture = TestBed.createComponent(Page) + fixture.detectChanges() + const [successQuery, errorQuery] = fixture.componentInstance.queries() + + expect(successQuery.status()).toBe('pending') + expect(errorQuery.status()).toBe('pending') + + const stablePromise = app.whenStable() + await Promise.resolve() + await vi.advanceTimersByTimeAsync(10) + await stablePromise + + expect(successQuery.status()).toBe('success') + expect(successQuery.data()).toBe('instant-data') + expect(errorQuery.status()).toBe('error') + expect(errorQuery.error()).toEqual(new Error('instant-error')) + }) + + it('tracks invalidation even when combine returns an unchanged value', async () => { + vi.useRealTimers() + const key = ['combined-pending-invalidation'] + let complete!: (value: number) => void + let calls = 0 + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [ + { + queryKey: key, + queryFn: () => + ++calls === 1 + ? 1 + : new Promise((resolve) => { + complete = resolve + }), + }, + ], + combine: () => 'unchanged', + })), + ) + const app = TestBed.inject(ApplicationRef) + await app.whenStable() + expect(queries()).toBe('unchanged') + let isStable = false + const subscription = app.isStable.subscribe((value) => { + isStable = value + }) + expect(isStable).toBe(true) + + const invalidation = queryClient.invalidateQueries({ queryKey: key }) + expect(isStable).toBe(false) + complete(2) + await invalidation + await app.whenStable() + expect(isStable).toBe(true) + expect(queries()).toBe('unchanged') + subscription.unsubscribe() + }) + + it('should not register pending tasks for disabled queries', async () => { + const queryFn = vi.fn(() => Promise.resolve('disabled-data')) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['queries-disabled-enabled'], + queryFn, + enabled: false, + }, + { + queryKey: ['queries-disabled-skip-token'], + queryFn: skipToken, + }, + ], + })) + } + + const fixture = TestBed.createComponent(Page) + fixture.detectChanges() + await Promise.resolve() + + const [disabledQuery, skippedQuery] = fixture.componentInstance.queries() + expect(disabledQuery.fetchStatus()).toBe('idle') + expect(skippedQuery.fetchStatus()).toBe('idle') + expect(queryFn).not.toHaveBeenCalled() + expect(fixture.isStable()).toBe(true) + }) + + it('should stay pending while queries are paused offline', async () => { + const app = TestBed.inject(ApplicationRef) + onlineManager.setOnline(false) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['queries-start-offline'], + queryFn: () => sleep(10).then(() => 'online-data'), + }, + ], + })) + } + + const fixture = TestBed.createComponent(Page) + fixture.detectChanges() + await Promise.resolve() + + const query = fixture.componentInstance.queries()[0] + expect(query.fetchStatus()).toBe('paused') + + let stableResolved = false + const stablePromise = app.whenStable().then(() => { + stableResolved = true + }) + await Promise.resolve() + expect(stableResolved).toBe(false) + + onlineManager.setOnline(true) + await vi.advanceTimersByTimeAsync(20) + await stablePromise + + expect(query.status()).toBe('success') + expect(query.data()).toBe('online-data') + }) + + it('should handle rapid refetches without leaking a pending task', async () => { + const app = TestBed.inject(ApplicationRef) + let count = 0 + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['queries-rapid-refetch'], + queryFn: async () => { + await sleep(10) + return ++count + }, + }, + ], + })) + } + + const fixture = TestBed.createComponent(Page) + fixture.detectChanges() + const query = fixture.componentInstance.queries()[0] + + query.refetch() + query.refetch() + query.refetch() + + const stablePromise = app.whenStable() + await vi.advanceTimersByTimeAsync(20) + await stablePromise + + expect(query.status()).toBe('success') + expect(query.data()).toBeGreaterThan(0) + expect(fixture.isStable()).toBe(true) + }) + + it('should release the pending task when a query is cancelled', async () => { + const app = TestBed.inject(ApplicationRef) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['queries-cancel'], + queryFn: () => sleep(100).then(() => 'data'), + }, + ], + })) + } + + const fixture = TestBed.createComponent(Page) + fixture.detectChanges() + const query = fixture.componentInstance.queries()[0] + + await vi.advanceTimersByTimeAsync(20) + await queryClient.cancelQueries({ queryKey: ['queries-cancel'] }) + await app.whenStable() + + expect(query.status()).toBe('pending') + expect(query.fetchStatus()).toBe('idle') + expect(fixture.isStable()).toBe(true) + }) + + it('should keep the pending task through retries', async () => { + const app = TestBed.inject(ApplicationRef) + let attemptCount = 0 + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['queries-retry'], + retry: 2, + retryDelay: 10, + queryFn: () => { + attemptCount++ + if (attemptCount <= 2) { + throw new Error(`Attempt ${attemptCount} failed`) + } + return 'success-data' + }, + }, + ], + })) + } + + const fixture = TestBed.createComponent(Page) + fixture.detectChanges() + const query = fixture.componentInstance.queries()[0] + + const stablePromise = app.whenStable() + await vi.advanceTimersByTimeAsync(50) + await stablePromise + + expect(query.status()).toBe('success') + expect(query.data()).toBe('success-data') + expect(attemptCount).toBe(3) + }) + }) + + it('should pause fetching while restoring and fetch once restoring is disabled', async () => { + const isRestoring = signal(true) + const fetchSpy = vi.fn(() => sleep(10).then(() => 'restored-data')) + setupTanStackQueryTestBed(queryClient, { + providers: [provideIsRestoring(() => isRestoring.asReadonly())], + }) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['restoring'], + queryFn: fetchSpy, + }, + ], + })) + } + + const fixture = TestBed.createComponent(Page) + fixture.detectChanges() + + expect(fetchSpy).not.toHaveBeenCalled() + expect(fixture.componentInstance.queries()[0].status()).toBe('pending') + + const stablePromise = fixture.whenStable() + await Promise.resolve() + await stablePromise + + isRestoring.set(false) + fixture.detectChanges() + + await vi.advanceTimersByTimeAsync(11) + await fixture.whenStable() + + const result = fixture.componentInstance.queries()[0] + expect(fetchSpy).toHaveBeenCalledTimes(1) + expect(result.status()).toBe('success') + expect(result.data()).toBe('restored-data') + + const cachedQuery = queryClient + .getQueryCache() + .find({ queryKey: ['restoring'] })! + expect(cachedQuery.getObserversCount()).toBe(1) + + isRestoring.set(true) + fixture.detectChanges() + expect(cachedQuery.getObserversCount()).toBe(0) + + isRestoring.set(false) + fixture.detectChanges() + expect(cachedQuery.getObserversCount()).toBe(1) + + fixture.destroy() + expect(cachedQuery.getObserversCount()).toBe(0) + }) + + it.each(['options-first', 'restoring-first'] as const)( + 'uses the latest query list when leaving restoration in the same turn (%s)', + async (writeOrder) => { + const isRestoring = signal(true) + const key = signal('old') + const queriedKeys: Array = [] + setupTanStackQueryTestBed(queryClient, { + providers: [provideIsRestoring(() => isRestoring.asReadonly())], + }) + + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [ + { + queryKey: ['same-turn-restoration', key()], + queryFn: ({ queryKey: currentQueryKey }) => { + const currentKey = currentQueryKey[1] as string + queriedKeys.push(currentKey) + return Promise.resolve(currentKey) + }, + }, + ], + })), + ) + + expect(queries()[0].status()).toBe('pending') + expect(queriedKeys).toEqual([]) + + if (writeOrder === 'options-first') { + key.set('new') + isRestoring.set(false) + } else { + isRestoring.set(false) + key.set('new') + } + TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() + + expect(queriedKeys).toEqual(['new']) + expect(queries()[0].data()).toBe('new') + expect( + queryClient + .getQueryCache() + .find({ queryKey: ['same-turn-restoration', 'old'] })?.state + .fetchStatus, + ).toBe('idle') + expect( + queryClient + .getQueryCache() + .find({ queryKey: ['same-turn-restoration', 'new'] }) + ?.getObserversCount(), + ).toBe(1) + }, + ) + + it('allows a cache listener to read a result during restoration-boundary configuration', () => { + const isRestoring = signal(true) + const staleTime = signal(0) + setupTanStackQueryTestBed(queryClient, { + providers: [provideIsRestoring(() => isRestoring.asReadonly())], + }) + + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [ + { + queryKey: ['restoration-reentrant'], + queryFn: () => 'data', + enabled: false, + staleTime: staleTime(), + }, + ], + })), + ) + + expect(queries()[0].status()).toBe('pending') + TestBed.tick() + + const boundaryRead = vi.fn(() => queries()[0].status()) + let appliedStaleTime: number | undefined + const unsubscribe = queryClient.getQueryCache().subscribe((event) => { + if (event.type === 'observerOptionsUpdated') { + appliedStaleTime = event.observer.options.staleTime as number + boundaryRead() + } + }) + + staleTime.set(1) + isRestoring.set(false) + + expect(() => TestBed.tick()).not.toThrow() + expect(boundaryRead).toHaveBeenCalled() + expect(appliedStaleTime).toBe(1) + expect( + queryClient + .getQueryCache() + .find({ queryKey: ['restoration-reentrant'] }) + ?.getObserversCount(), + ).toBe(1) + + unsubscribe() + }) + + it('converges to the current query list after an early restoration read', () => { + const isRestoring = signal(true) + const key = signal('old') + const oldQueryKey = ['early-restoration-read', 'old'] as const + const newQueryKey = ['early-restoration-read', 'new'] as const + setupTanStackQueryTestBed(queryClient, { + providers: [provideIsRestoring(() => isRestoring.asReadonly())], + }) + + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [ + { + queryKey: ['early-restoration-read', key()], + queryFn: () => 'unused', + enabled: false, + }, + ], + })), + ) + + expect(queries()[0].status()).toBe('pending') + TestBed.tick() + const oldQuery = queryClient + .getQueryCache() + .find({ queryKey: oldQueryKey })! + expect(oldQuery.getObserversCount()).toBe(0) + + key.set('new') + isRestoring.set(false) + + expect(queries()[0].status()).toBe('pending') + expect( + queryClient.getQueryCache().find({ queryKey: newQueryKey }), + ).toBeDefined() + + queryClient.setQueryData(newQueryKey, 'early data') + const newQuery = queryClient + .getQueryCache() + .find({ queryKey: newQueryKey })! + expect(newQuery.getObserversCount()).toBe(0) + TestBed.tick() + + expect(oldQuery.getObserversCount()).toBe(0) + expect(newQuery.getObserversCount()).toBe(1) + expect(queries()[0].data()).toBe('early data') + }) + + it('reads the optimistic query list before moving subscriptions on the next tick', () => { + const key = signal('old') + const oldQueryKey = ['early-options-read', 'old'] as const + const newQueryKey = ['early-options-read', 'new'] as const + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [ + { + queryKey: ['early-options-read', key()], + queryFn: () => 'unused', + enabled: false, + }, + ], + })), + ) + + expect(queries()[0].status()).toBe('pending') + TestBed.tick() + const oldQuery = queryClient + .getQueryCache() + .find({ queryKey: oldQueryKey })! + expect(oldQuery.getObserversCount()).toBe(1) + + key.set('new') + + expect(queries()[0].status()).toBe('pending') + // The existing observer list stays attached until the configuration effect + // can move it atomically. + expect(oldQuery.getObserversCount()).toBe(1) + expect( + queryClient.getQueryCache().find({ queryKey: newQueryKey }), + ).toBeDefined() + + queryClient.setQueryData(newQueryKey, 'early data') + const newQuery = queryClient + .getQueryCache() + .find({ queryKey: newQueryKey })! + expect(newQuery.getObserversCount()).toBe(0) + TestBed.tick() + + expect(oldQuery.getObserversCount()).toBe(0) + expect(newQuery.getObserversCount()).toBe(1) + expect(queries()[0].data()).toBe('early data') + }) + + it('should complete queries before whenStable resolves', async () => { + const app = TestBed.inject(ApplicationRef) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['query-1'], + queryFn: async () => { + await new Promise((resolve) => setTimeout(resolve, 10)) + return 1 + }, + }, + { + queryKey: ['query-2'], + queryFn: async () => { + await new Promise((resolve) => setTimeout(resolve, 20)) + return 2 + }, + }, + ], + })) + } + + const fixture = TestBed.createComponent(Page) + fixture.detectChanges() + + const stablePromise = app.whenStable() + let stableResolved = false + void stablePromise.then(() => { + stableResolved = true + }) + + await Promise.resolve() + expect(stableResolved).toBe(false) + + await vi.advanceTimersByTimeAsync(25) + await stablePromise + + const result = fixture.componentInstance.queries() + expect(result[0].status()).toBe('success') + expect(result[1].status()).toBe('success') + expect(result[0].data()).toBe(1) + expect(result[1].data()).toBe(2) + }) + + it('should use latest query key for aliased refetch function', async () => { + const key = signal('one') + const fetchSpy = vi.fn(async (context: any) => { + await new Promise((resolve) => setTimeout(resolve, 10)) + return context.queryKey[1] + }) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class Page { + key = key + fetchSpy = fetchSpy + + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['query', this.key()], + queryFn: this.fetchSpy, + enabled: false, + }, + ], + })) + } + + const rendered = await render(Page) + const query = rendered.fixture.componentInstance.queries()[0] + const refetch = query.refetch + + key.set('two') + rendered.fixture.detectChanges() + + const refetchPromise = refetch() + await vi.advanceTimersByTimeAsync(15) + await refetchPromise + + expect(fetchSpy).toHaveBeenCalledTimes(1) + expect(fetchSpy).toHaveBeenCalledWith( + expect.objectContaining({ + queryKey: ['query', 'two'], + }), + ) + }) +}) diff --git a/packages/angular-query/src/__tests__/inject-query-lifecycle.test.ts b/packages/angular-query/src/__tests__/inject-query-lifecycle.test.ts new file mode 100644 index 00000000000..77f67a79744 --- /dev/null +++ b/packages/angular-query/src/__tests__/inject-query-lifecycle.test.ts @@ -0,0 +1,79 @@ +import { DestroyRef, NgZone, PendingTasks, runInInjectionContext } from '@angular/core' +import { describe, expect, it, vi } from 'vitest' +import { injectPendingTasksLifecycle } from '../utils/inject-pending-tasks-lifecycle' +import type { Injector } from '@angular/core' + +function setupLifecycle() { + const destroyCallbacks: Array<() => void> = [] + const taskCleanups: Array> = [] + const pendingTasks = { + add: vi.fn(() => { + const cleanup = vi.fn() + taskCleanups.push(cleanup) + return cleanup + }), + } + const destroyRef: { + destroyed: boolean + onDestroy: ReturnType + } = { + destroyed: false, + onDestroy: vi.fn((callback: () => void) => { + destroyCallbacks.push(callback) + return () => { + const index = destroyCallbacks.indexOf(callback) + if (index !== -1) destroyCallbacks.splice(index, 1) + } + }), + } + const injector = { + get(token: unknown) { + if (token === NgZone) return { run: (callback: () => void) => callback() } + if (token === PendingTasks) return pendingTasks + if (token === DestroyRef) return destroyRef + throw new Error(`Unexpected token: ${String(token)}`) + }, + } as Injector + + return { + lifecycle: runInInjectionContext(injector, () => + injectPendingTasksLifecycle(), + ), + pendingTasks, + taskCleanups, + destroy: () => { + destroyRef.destroyed = true + for (const callback of [...destroyCallbacks]) callback() + }, + } +} + +describe('QueryLifecycle', () => { + it('tracks pending state without registering duplicate tasks', () => { + const { lifecycle, pendingTasks, taskCleanups } = setupLifecycle() + + lifecycle.setPending(true) + lifecycle.setPending(true) + + expect(pendingTasks.add).toHaveBeenCalledOnce() + + lifecycle.setPending(false) + expect(taskCleanups[0]).toHaveBeenCalledOnce() + + lifecycle.setPending(true) + expect(pendingTasks.add).toHaveBeenCalledTimes(2) + }) + + it('tracks destruction, releases its task, and cannot restart', () => { + const { lifecycle, pendingTasks, taskCleanups, destroy } = setupLifecycle() + + lifecycle.setPending(true) + destroy() + + expect(lifecycle.destroyed).toBe(true) + expect(taskCleanups[0]).toHaveBeenCalledOnce() + + lifecycle.setPending(true) + expect(pendingTasks.add).toHaveBeenCalledOnce() + }) +}) diff --git a/packages/angular-query/src/__tests__/inject-query.test-d.ts b/packages/angular-query/src/__tests__/inject-query.test-d.ts new file mode 100644 index 00000000000..ecc517df018 --- /dev/null +++ b/packages/angular-query/src/__tests__/inject-query.test-d.ts @@ -0,0 +1,250 @@ +import { describe, expectTypeOf, it } from 'vitest' +import { sleep } from '@tanstack/query-test-utils' +import { injectQuery, queryOptions, toResource } from '..' +import type { CreateQueryOptions } from '..' +import type { Resource, Signal } from '@angular/core' + +describe('initialData', () => { + describe('Config object overload', () => { + it('TData should always be defined when initialData is provided as an object', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => ({ wow: true }), + initialData: { wow: true }, + })) + const resource = toResource(query) + + expectTypeOf(query.data).toEqualTypeOf>() + expectTypeOf(resource.value).toEqualTypeOf>() + }) + + it('TData should be defined when passed through queryOptions', () => { + const options = () => + queryOptions({ + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + const { data } = injectQuery(options) + + expectTypeOf(data).toEqualTypeOf>() + }) + + it('should support selection function with select', () => { + const options = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => '1', + select: (data) => { + expectTypeOf(data).toEqualTypeOf() + return parseInt(data) + }, + })) + expectTypeOf(options.data).toEqualTypeOf>() + }) + + it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => { + const options = queryOptions({ + queryKey: ['key'], + queryFn: () => Promise.resolve(1), + }) + + const query = injectQuery(() => ({ + ...options, + select: (data) => data > 1, + })) + + expectTypeOf(query.data).toEqualTypeOf>() + }) + + it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => { + const { data } = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => ({ + wow: true, + }), + })) + + expectTypeOf(data).toEqualTypeOf>() + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + const { data } = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } + }, + })) + + expectTypeOf(data).toEqualTypeOf>() + }) + + it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { + const { data } = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => undefined as { wow: boolean } | undefined, + })) + + expectTypeOf(data).toEqualTypeOf>() + }) + + it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => undefined as { wow: boolean } | undefined, + })) + + if (query.isSuccess()) { + expectTypeOf(query.data).toEqualTypeOf>() + } + }) + + it('should keep data defined after an isError check when initialData is provided', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => Promise.resolve('Some data'), + initialData: 'initial data', + })) + + if (query.isError()) { + expectTypeOf(query.data).toEqualTypeOf>() + } + }) + + it('should make an isPending branch impossible when initialData is provided', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => Promise.resolve('Some data'), + initialData: 'initial data', + })) + + if (query.isPending()) { + expectTypeOf(query).toEqualTypeOf() + } + }) + }) + + describe('structuralSharing', () => { + it('should be able to use structuralSharing with unknown types', () => { + // https://github.com/TanStack/query/issues/6525#issuecomment-1938411343 + injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => 5, + structuralSharing: (oldData, newData) => { + expectTypeOf(oldData).toBeUnknown() + expectTypeOf(newData).toBeUnknown() + return newData + }, + })) + }) + }) +}) + +describe('Discriminated union return type', () => { + it('should expose status predicates as Angular signals', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => sleep(0).then(() => 'Some data'), + })) + + expectTypeOf(query.isSuccess).toMatchTypeOf>() + expectTypeOf(query.isError).toMatchTypeOf>() + expectTypeOf(query.isPending).toMatchTypeOf>() + }) + + it('should expose an Angular resource view', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => sleep(0).then(() => 'Some data'), + })) + + const resource = toResource(query) + expectTypeOf(resource).toMatchTypeOf>() + expectTypeOf(resource.reload).toBeCallableWith() + + // @ts-expect-error Resources are created explicitly with toResource. + query.resource + }) + + it('data should be possibly undefined by default', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => sleep(0).then(() => 'Some data'), + })) + + expectTypeOf(query.data).toEqualTypeOf>() + }) + + it('data should be defined when query is success', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => sleep(0).then(() => 'Some data'), + })) + + if (query.isSuccess()) { + expectTypeOf(query.data).toEqualTypeOf>() + expectTypeOf(toResource(query).value).toEqualTypeOf>() + } + }) + + it('error should be null when query is success', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => sleep(0).then(() => 'Some data'), + })) + + if (query.isSuccess()) { + expectTypeOf(query.error).toEqualTypeOf>() + } + }) + + it('data should be undefined when query is pending', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => sleep(0).then(() => 'Some data'), + })) + + if (query.isPending()) { + expectTypeOf(query.data).toEqualTypeOf>() + } + }) + + it('error should be defined when query is error', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => sleep(0).then(() => 'Some data'), + })) + + if (query.isError()) { + expectTypeOf(query.error).toEqualTypeOf>() + } + }) +}) + +describe('injectQuery options', () => { + it('omits observer error reporting options', () => { + expectTypeOf().not.toHaveProperty('throwOnError') + }) +}) diff --git a/packages/angular-query/src/__tests__/inject-query.test.ts b/packages/angular-query/src/__tests__/inject-query.test.ts new file mode 100644 index 00000000000..29f082632e3 --- /dev/null +++ b/packages/angular-query/src/__tests__/inject-query.test.ts @@ -0,0 +1,1636 @@ +import { + ApplicationRef, + ChangeDetectionStrategy, + Component, + ErrorHandler, + computed, + effect, + input, + inputBinding, + signal, +} from '@angular/core' +import { TestBed } from '@angular/core/testing' +import { HttpClient, provideHttpClient } from '@angular/common/http' +import { + HttpTestingController, + provideHttpClientTesting, +} from '@angular/common/http/testing' +import { + afterEach, + beforeEach, + describe, + expect, + expectTypeOf, + it, + vi, +} from 'vitest' +import { render } from '@testing-library/angular' +import { queryKey, sleep } from '@tanstack/query-test-utils' +import { lastValueFrom } from 'rxjs' +import { provideIsRestoring } from '../internal' +import { + QueryCache, + QueryClient, + injectQuery, + provideTanStackQuery, + toResource, +} from '..' +import { provideAngularQueryChangeDetection } from './test-utils' +import type { CreateQueryOptions, OmitKeyof, QueryFunction } from '..' + +// cspell:ignore ZONEFUL + +describe('injectQuery', () => { + let queryCache: QueryCache + let queryClient: QueryClient + beforeEach(() => { + vi.useFakeTimers() + queryCache = new QueryCache() + queryClient = new QueryClient({ queryCache }) + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + }) + + afterEach(() => { + vi.useRealTimers() + }) + + it('should keep failed refetch state and cached data readable without global reporting', async () => { + vi.useRealTimers() + queryClient.setDefaultOptions({ + queries: { retry: false, throwOnError: true }, + }) + const report = vi.spyOn(TestBed.inject(ErrorHandler), 'handleError') + const error = new Error('query failed') + const options = { + queryKey: ['error'], + initialData: 'cached', + enabled: false, + queryFn: async (): Promise => { + throw error + }, + } + const query = TestBed.runInInjectionContext(() => + injectQuery(() => options), + ) + const cacheReport = vi.fn() + queryCache.config.onError = cacheReport + const second = TestBed.runInInjectionContext(() => + injectQuery(() => options), + ) + await TestBed.inject(ApplicationRef).whenStable() + await expect(query.refetch()).resolves.toMatchObject({ + status: 'error', + error, + }) + expect(query.error()).toBe(error) + expect(second.error()).toBe(error) + expect(cacheReport).toHaveBeenCalledTimes(1) + expect(query.data()).toBe('cached') + expect(query.isError()).toBe(true) + await expect(query.refetch({ throwOnError: true })).rejects.toBe(error) + expect(report).not.toHaveBeenCalled() + }) + + it('should return the correct types', () => { + const key = queryKey() + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + // unspecified query function should default to unknown + noQueryFn = injectQuery(() => ({ + queryKey: key, + })) + + // it should infer the result type from the query function + fromQueryFn = injectQuery(() => ({ + queryKey: key, + queryFn: () => 'test', + })) + + // it should be possible to specify the result type + withResult = injectQuery(() => ({ + queryKey: key, + queryFn: () => 'test', + })) + + // it should be possible to specify the error type + withError = injectQuery(() => ({ + queryKey: key, + queryFn: () => 'test', + })) + + // it should infer the result type from the configuration + withResultInfer = injectQuery(() => ({ + queryKey: key, + queryFn: () => true, + })) + + // it should be possible to specify a union type as result type + unionTypeSync = injectQuery(() => ({ + queryKey: key, + queryFn: () => (Math.random() > 0.5 ? ('a' as const) : ('b' as const)), + })) + + unionTypeAsync = injectQuery<'a' | 'b'>(() => ({ + queryKey: key, + queryFn: () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'), + })) + + // it should infer the result type from a generic query function + fromGenericQueryFn = (() => { + function queryFn(): Promise { + return Promise.resolve({} as T) + } + return injectQuery(() => ({ + queryKey: key, + queryFn: () => queryFn(), + })) + })() + + // todo use query options? + fromGenericOptionsQueryFn = (() => { + function queryFn(): Promise { + return Promise.resolve({} as T) + } + return injectQuery(() => ({ + queryKey: key, + queryFn: () => queryFn(), + })) + })() + + fromMyDataArrayKeyQueryFn = (() => { + type MyData = number + type MyQueryKey = readonly ['my-data', number] + const getMyDataArrayKey: QueryFunction = ({ + queryKey: [, n], + }) => { + return n + 42 + } + return injectQuery(() => ({ + queryKey: ['my-data', 100] as const, + queryFn: getMyDataArrayKey, + })) + })() + + // it should handle query-functions that return Promise + fromPromiseAnyQueryFn = injectQuery(() => ({ + queryKey: key, + queryFn: () => fetch('return Promise').then((resp) => resp.json()), + })) + + fromGetMyDataStringKeyQueryFn = (() => { + type MyData = number + const getMyDataStringKey: QueryFunction = (context) => { + expectTypeOf(context.queryKey).toEqualTypeOf<['1']>() + return Number(context.queryKey[0]) + 42 + } + return injectQuery(() => ({ + queryKey: ['1'] as ['1'], + queryFn: getMyDataStringKey, + })) + })() + + // Wrapped queries + fromWrappedQuery = (() => { + const createWrappedQuery = < + TQueryKey extends [string, Record?], + TQueryFnData, + TError, + TData = TQueryFnData, + >( + qk: TQueryKey, + fetcher: (obj: TQueryKey[1], token: string) => Promise, + options?: OmitKeyof< + CreateQueryOptions, + 'queryKey' | 'queryFn' | 'initialData', + 'safely' + >, + ) => + injectQuery(() => ({ + queryKey: qk, + queryFn: () => fetcher(qk[1], 'token'), + ...options, + })) + return createWrappedQuery([''], () => Promise.resolve('1')) + })() + + fromWrappedFuncStyleQuery = (() => { + const createWrappedFuncStyleQuery = < + TQueryKey extends [string, Record?], + TQueryFnData, + TError, + TData = TQueryFnData, + >( + qk: TQueryKey, + fetcher: () => Promise, + options?: OmitKeyof< + CreateQueryOptions, + 'queryKey' | 'queryFn' | 'initialData', + 'safely' + >, + ) => injectQuery(() => ({ queryKey: qk, queryFn: fetcher, ...options })) + return createWrappedFuncStyleQuery([''], () => Promise.resolve(true)) + })() + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const { + noQueryFn, + fromQueryFn, + withResult, + withError, + withResultInfer, + unionTypeSync, + unionTypeAsync, + fromGenericQueryFn, + fromGenericOptionsQueryFn, + fromMyDataArrayKeyQueryFn, + fromPromiseAnyQueryFn, + fromGetMyDataStringKeyQueryFn, + fromWrappedQuery, + fromWrappedFuncStyleQuery, + } = fixture.componentInstance + + expectTypeOf(noQueryFn.data()).toEqualTypeOf() + expectTypeOf(noQueryFn.error()).toEqualTypeOf() + + expectTypeOf(fromQueryFn.data()).toEqualTypeOf() + expectTypeOf(fromQueryFn.error()).toEqualTypeOf() + + expectTypeOf(withResult.data()).toEqualTypeOf() + expectTypeOf(withResult.error()).toEqualTypeOf() + + expectTypeOf(withError.data()).toEqualTypeOf() + expectTypeOf(withError.error()).toEqualTypeOf<{ message: string } | null>() + + expectTypeOf(withResultInfer.data()).toEqualTypeOf() + expectTypeOf(withResultInfer.error()).toEqualTypeOf() + + expectTypeOf(unionTypeSync.data()).toEqualTypeOf<'a' | 'b' | undefined>() + expectTypeOf(unionTypeAsync.data()).toEqualTypeOf<'a' | 'b' | undefined>() + + expectTypeOf(fromGenericQueryFn.data()).toEqualTypeOf() + expectTypeOf(fromGenericQueryFn.error()).toEqualTypeOf() + + expectTypeOf(fromGenericOptionsQueryFn.data()).toEqualTypeOf< + string | undefined + >() + expectTypeOf( + fromGenericOptionsQueryFn.error(), + ).toEqualTypeOf() + + expectTypeOf(fromMyDataArrayKeyQueryFn.data()).toEqualTypeOf< + number | undefined + >() + + expectTypeOf(fromPromiseAnyQueryFn.data()).toEqualTypeOf() + expectTypeOf(fromGetMyDataStringKeyQueryFn.data()).toEqualTypeOf< + number | undefined + >() + expectTypeOf(fromWrappedQuery.data()).toEqualTypeOf() + expectTypeOf(fromWrappedFuncStyleQuery.data()).toEqualTypeOf< + boolean | undefined + >() + }) + + it('should return pending status initially', () => { + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectQuery(() => ({ + queryKey: ['key1'], + queryFn: () => sleep(10).then(() => 'Some data'), + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + fixture.autoDetectChanges() + const query = fixture.componentInstance.query + + expect(query.status()).toBe('pending') + expect(query.isPending()).toBe(true) + expect(query.isFetching()).toBe(true) + expect(query.isStale()).toBe(true) + expect(query.isFetched()).toBe(false) + }) + + it('should resolve to success and update signal: injectQuery()', async () => { + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectQuery(() => ({ + queryKey: ['key2'], + queryFn: () => sleep(10).then(() => 'result2'), + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + await vi.advanceTimersByTimeAsync(11) + expect(query.status()).toBe('success') + expect(query.data()).toBe('result2') + expect(query.isPending()).toBe(false) + expect(query.isFetching()).toBe(false) + expect(query.isFetched()).toBe(true) + expect(query.isSuccess()).toBe(true) + }) + + it('should reject and update signal', async () => { + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectQuery(() => ({ + retry: false, + queryKey: ['key3'], + queryFn: () => + sleep(10).then(() => Promise.reject(new Error('Some error'))), + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + await vi.advanceTimersByTimeAsync(11) + expect(query.status()).toBe('error') + expect(query.data()).toBe(undefined) + expect(query.error()).toMatchObject({ message: 'Some error' }) + expect(query.isPending()).toBe(false) + expect(query.isFetching()).toBe(false) + expect(query.isError()).toBe(true) + expect(query.failureCount()).toBe(1) + expect(query.failureReason()).toMatchObject({ message: 'Some error' }) + }) + + it('should expose the query result as an Angular resource', async () => { + const queryFn = vi.fn(() => sleep(10).then(() => 'result')) + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['resource-query'], + queryFn, + })), + ) + + TestBed.tick() + expect('resource' in query).toBe(false) + const resource = toResource(query) + expect(resource.status()).toBe('loading') + expect(resource.snapshot()).toEqual({ status: 'loading', value: undefined }) + expect(resource.isLoading()).toBe(true) + expect(resource.hasValue()).toBe(false) + + await vi.advanceTimersByTimeAsync(11) + + expect(resource.status()).toBe('resolved') + expect(resource.snapshot()).toEqual({ status: 'resolved', value: 'result' }) + expect(resource.isLoading()).toBe(false) + expect(resource.hasValue()).toBe(true) + expect(resource.value()).toBe('result') + + expect(resource.reload()).toBe(true) + await Promise.resolve() + expect(queryFn).toHaveBeenCalledTimes(2) + + expect(resource.status()).toBe('reloading') + expect(resource.snapshot()).toEqual({ + status: 'reloading', + value: 'result', + }) + expect(resource.isLoading()).toBe(true) + expect(resource.value()).toBe('result') + expect(resource.reload()).toBe(false) + expect(queryFn).toHaveBeenCalledTimes(2) + + await vi.advanceTimersByTimeAsync(11) + + expect(resource.status()).toBe('resolved') + expect(resource.value()).toBe('result') + }) + + it.each([undefined, null, 'query failed'])( + 'should normalize a %s query rejection for the resource error state', + async (rejection) => { + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['resource-query-error', rejection], + queryFn: () => Promise.reject(rejection), + retry: false, + })), + ) + + TestBed.tick() + await vi.advanceTimersByTimeAsync(1) + + const resource = toResource(query) + const resourceError = resource.error() + expect(resource.status()).toBe('error') + expect(resourceError).toBeInstanceOf(Error) + expect(resourceError?.cause).toBe(rejection) + expect(resource.snapshot()).toEqual({ + status: 'error', + error: resourceError, + }) + + let thrown: unknown + try { + resource.value() + } catch (error) { + thrown = error + } + expect(thrown).toBe(resourceError) + }, + ) + + it('should preserve Error-like query rejections', async () => { + const rejection = { name: 'QueryError', message: 'query failed' } + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['resource-query-error-like'], + queryFn: () => Promise.reject(rejection), + retry: false, + })), + ) + + TestBed.tick() + await vi.advanceTimersByTimeAsync(1) + + const resource = toResource(query) + expect(resource.status()).toBe('error') + expect(resource.error()).toBe(rejection) + }) + + it('should not reload fresh query resources', async () => { + const queryFn = vi.fn(() => sleep(10).then(() => 'fresh-result')) + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['fresh-resource-query'], + queryFn, + staleTime: Infinity, + })), + ) + + TestBed.tick() + await vi.advanceTimersByTimeAsync(11) + + const resource = toResource(query) + expect(resource.status()).toBe('resolved') + expect(resource.reload()).toBe(false) + expect(queryFn).toHaveBeenCalledTimes(1) + }) + + it('should expose disabled queries as idle resources', () => { + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + enabled: false, + queryKey: ['idle-resource-query'], + queryFn: () => sleep(10).then(() => 'result'), + })), + ) + + TestBed.tick() + const resource = toResource(query) + + expect(resource.status()).toBe('idle') + expect(resource.snapshot()).toEqual({ status: 'idle', value: undefined }) + expect(resource.isLoading()).toBe(false) + expect(resource.hasValue()).toBe(false) + expect(resource.value()).toBe(undefined) + expect(resource.reload()).toBe(false) + }) + + it('should update query on options contained signal change', async () => { + const key = signal(['key6', 'key7']) + const spy = vi.fn(() => sleep(10).then(() => 'Some data')) + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + key = key + spy = spy + query = injectQuery(() => ({ + queryKey: this.key(), + queryFn: this.spy, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + await vi.advanceTimersByTimeAsync(0) + expect(spy).toHaveBeenCalledTimes(1) + + await vi.advanceTimersByTimeAsync(10) + expect(query.status()).toBe('success') + + key.set(['key8']) + fixture.detectChanges() + + expect(spy).toHaveBeenCalledTimes(2) + // should call queryFn with context containing the new queryKey + expect(spy).toHaveBeenNthCalledWith(2, { + client: queryClient, + meta: undefined, + queryKey: ['key8'], + signal: expect.anything(), + }) + }) + + it('allows cache listeners to read the result while options update', () => { + const key = signal('one') + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['reentrant-options', key()], + queryFn: () => 'data', + enabled: false, + })), + ) + + TestBed.tick() + const readResult = vi.fn(() => query.status()) + const unsubscribe = queryCache.subscribe((event) => { + // setOptions emits synchronously; this read must not re-enter the signal + // computation that caused the options update. + if (event.type === 'observerOptionsUpdated') readResult() + }) + + key.set('two') + + expect(() => TestBed.tick()).not.toThrow() + expect(readResult).toHaveBeenCalled() + + unsubscribe() + }) + + it('allows deferred cache-listener reads during restoration detach and reattach', async () => { + const isRestoring = signal(false) + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + provideIsRestoring(() => isRestoring.asReadonly()), + ], + }) + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['reentrant-restoration-subscription'], + queryFn: () => 'data', + enabled: false, + })), + ) + expect(query.status()).toBe('pending') + TestBed.tick() + + const nestedStatuses: Array = [] + const unsubscribe = queryCache.subscribe((event) => { + if (event.type === 'observerAdded' || event.type === 'observerRemoved') { + void Promise.resolve().then(() => nestedStatuses.push(query.status())) + } + }) + + isRestoring.set(true) + expect(() => TestBed.tick()).not.toThrow() + isRestoring.set(false) + expect(() => TestBed.tick()).not.toThrow() + + await Promise.resolve() + expect(nestedStatuses).toEqual(['pending', 'pending']) + unsubscribe() + }) + + it('allows deferred cache-listener reads while an option change creates a query', async () => { + const key = signal('old') + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['reentrant-query-added', key()], + queryFn: () => 'data', + enabled: false, + })), + ) + + expect(query.status()).toBe('pending') + TestBed.tick() + const nestedStatuses: Array = [] + const unsubscribe = queryCache.subscribe((event) => { + if (event.type === 'added') + void Promise.resolve().then(() => nestedStatuses.push(query.status())) + }) + + key.set('new') + + expect(() => query.status()).not.toThrow() + expect(nestedStatuses).toEqual([]) + expect(() => TestBed.tick()).not.toThrow() + await Promise.resolve() + expect(nestedStatuses).toEqual(['pending']) + unsubscribe() + }) + + it('keeps the external subscription when non-key options change', () => { + const staleTime = signal(0) + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['stable-option-subscription'], + queryFn: () => 'data', + enabled: false, + staleTime: staleTime(), + })), + ) + + expect(query.status()).toBe('pending') + TestBed.tick() + const cachedQuery = queryCache.find({ + queryKey: ['stable-option-subscription'], + })! + const subscriptionEvents: Array = [] + const unsubscribe = queryCache.subscribe((event) => { + if (event.type === 'observerAdded' || event.type === 'observerRemoved') { + subscriptionEvents.push(event.type) + } + }) + + staleTime.set(1) + expect(query.status()).toBe('pending') + TestBed.tick() + + expect(cachedQuery.getObserversCount()).toBe(1) + expect(subscriptionEvents).toEqual([]) + unsubscribe() + }) + + it('should only run query once enabled signal is set to true', async () => { + const spy = vi.fn(() => sleep(10).then(() => 'Some data')) + const enabled = signal(false) + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + enabled = enabled + spy = spy + query = injectQuery(() => ({ + queryKey: ['key9'], + queryFn: this.spy, + enabled: this.enabled(), + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + expect(spy).not.toHaveBeenCalled() + expect(query.status()).toBe('pending') + + enabled.set(true) + fixture.detectChanges() + + await vi.advanceTimersByTimeAsync(10) + expect(spy).toHaveBeenCalledTimes(1) + expect(query.status()).toBe('success') + }) + + it('should properly execute dependant queries', async () => { + const dependentQueryFn = vi + .fn() + .mockImplementation(() => sleep(1000).then(() => 'Some data')) + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query1 = injectQuery(() => ({ + queryKey: ['dependant1'], + queryFn: () => sleep(10).then(() => 'Some data'), + })) + + query2 = injectQuery( + computed(() => ({ + queryKey: ['dependent2'], + queryFn: dependentQueryFn, + enabled: !!this.query1.data(), + })), + ) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + fixture.autoDetectChanges() + const { query1, query2 } = fixture.componentInstance + + expect(query1.data()).toStrictEqual(undefined) + expect(query2.fetchStatus()).toStrictEqual('idle') + expect(dependentQueryFn).not.toHaveBeenCalled() + + await vi.advanceTimersByTimeAsync(11) + + expect(query1.data()).toStrictEqual('Some data') + expect(query2.fetchStatus()).toStrictEqual('fetching') + + await vi.advanceTimersByTimeAsync(1002) + + expect(query2.fetchStatus()).toStrictEqual('idle') + expect(query2.status()).toStrictEqual('success') + expect(dependentQueryFn).toHaveBeenCalledTimes(1) + expect(dependentQueryFn).toHaveBeenCalledWith( + expect.objectContaining({ queryKey: ['dependent2'] }), + ) + }) + + it('should use the current value for the queryKey when refetch is called', async () => { + const fetchFn = vi.fn(() => sleep(10).then(() => 'Some data')) + const keySignal = signal('key11') + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + keySignal = keySignal + fetchFn = fetchFn + query = injectQuery(() => ({ + queryKey: ['key10', this.keySignal()], + queryFn: this.fetchFn, + enabled: false, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + expect(fetchFn).not.toHaveBeenCalled() + + const first = query.refetch() + await vi.advanceTimersByTimeAsync(10) + await first + expect(fetchFn).toHaveBeenCalledTimes(1) + expect(fetchFn).toHaveBeenCalledWith( + expect.objectContaining({ + queryKey: ['key10', 'key11'], + }), + ) + + keySignal.set('key12') + const second = query.refetch() + await vi.advanceTimersByTimeAsync(10) + await second + expect(fetchFn).toHaveBeenCalledTimes(2) + expect(fetchFn).toHaveBeenCalledWith( + expect.objectContaining({ + queryKey: ['key10', 'key12'], + }), + ) + }) + + it('should keep initialData visible alongside the error when a refetch fails', async () => { + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectQuery(() => ({ + queryKey: ['initialDataError'], + queryFn: () => + sleep(10).then(() => Promise.reject(new Error('Some error'))), + initialData: 'initial', + retry: false, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + expect(query.data()).toBe('initial') + expect(query.isError()).toBe(false) + expect(query.status()).toBe('success') + + await vi.advanceTimersByTimeAsync(11) + fixture.detectChanges() + + expect(query.data()).toBe('initial') + expect(query.isError()).toBe(true) + expect(query.status()).toBe('error') + }) + + it('should support selection function with select', async () => { + const app = TestBed.inject(ApplicationRef) + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectQuery(() => ({ + queryKey: ['key13'], + queryFn: () => [{ id: 1 }, { id: 2 }], + select: (data) => data.map((item) => item.id), + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + // Wait for query to complete (even synchronous queryFn needs time to process) + const stablePromise = app.whenStable() + await Promise.resolve() + await vi.advanceTimersByTimeAsync(10) + await stablePromise + + expect(query.status()).toBe('success') + expect(query.data()).toEqual([1, 2]) + }) + + it('should set state to error when queryFn returns reject promise', async () => { + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectQuery(() => ({ + retry: false, + queryKey: ['key15'], + queryFn: () => + sleep(10).then(() => Promise.reject(new Error('Some error'))), + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + expect(query.status()).toBe('pending') + + await vi.advanceTimersByTimeAsync(11) + + expect(query.status()).toBe('error') + }) + + it('should render with required signal inputs', async () => { + @Component({ + selector: 'app-fake', + template: `{{ query.data() }}`, + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class FakeComponent { + name = input.required() + + query = injectQuery(() => ({ + queryKey: ['fake', this.name()], + queryFn: () => this.name(), + })) + } + + const name = signal('signal-input-required-test') + const rendered = await render(FakeComponent, { + bindings: [inputBinding('name', name.asReadonly())], + detectChangesOnRender: false, + }) + rendered.fixture.detectChanges() + rendered.fixture.autoDetectChanges() + await vi.advanceTimersByTimeAsync(0) + + const result = rendered.fixture.nativeElement.textContent + expect(result).toEqual('signal-input-required-test') + }) + + it('should support aliasing query.data on required signal inputs', async () => { + @Component({ + selector: 'app-fake', + template: `{{ data() }}`, + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class FakeComponent { + name = input.required() + + query = injectQuery(() => ({ + queryKey: ['fake-alias', this.name()], + queryFn: () => this.name(), + })) + + data = this.query.data + } + + const name = signal('signal-input-alias-test') + const rendered = await render(FakeComponent, { + bindings: [inputBinding('name', name.asReadonly())], + detectChangesOnRender: false, + }) + rendered.fixture.detectChanges() + rendered.fixture.autoDetectChanges() + await vi.advanceTimersByTimeAsync(0) + + const result = rendered.fixture.nativeElement.textContent + expect(result).toEqual('signal-input-alias-test') + }) + + it('should allow reading the query data on effect registered before injection', () => { + const spy = vi.fn() + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + readEffect = effect(() => { + spy(this.query.data()) + }) + + query = injectQuery(() => ({ + queryKey: ['effect-before-injection'], + queryFn: () => sleep(0).then(() => 'Some data'), + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + expect(spy).toHaveBeenCalledWith(undefined) + }) + + it('should render with an initial value for input signal if available before change detection', async () => { + const key1 = queryKey() as [string] + const key2 = queryKey() as [string] + queryClient.setQueryData(key1, 'value 1') + queryClient.setQueryData(key2, 'value 2') + + @Component({ + selector: 'app-test', + template: '{{ query.data() }}', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + inputKey = input.required<[string]>() + query = injectQuery(() => ({ + queryKey: this.inputKey(), + queryFn: () => sleep(0).then(() => 'Some data'), + })) + } + + const inputKey = signal<[string]>(key1) + const rendered = await render(TestComponent, { + bindings: [inputBinding('inputKey', inputKey.asReadonly())], + detectChangesOnRender: false, + }) + rendered.fixture.detectChanges() + + const instance = rendered.fixture.componentInstance + const query = instance.query + + expect(() => instance.inputKey()).not.toThrow() + + expect(instance.inputKey()).toEqual(key1) + expect(query.data()).toEqual('value 1') + + inputKey.set(key2) + rendered.fixture.detectChanges() + + expect(instance.inputKey()).toEqual(key2) + expect(query.data()).toEqual('value 2') + }) + + it('should allow reading the query data on component ngOnInit with required signal input', async () => { + const spy = vi.fn() + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + key = input.required<[string]>() + query = injectQuery(() => ({ + queryKey: this.key(), + queryFn: () => Promise.resolve(() => 'Some data'), + })) + + initialStatus!: string + + ngOnInit() { + this.initialStatus = this.query.status() + + // effect should not have been called yet + expect(spy).not.toHaveBeenCalled() + } + + _spyEffect = effect(() => { + spy() + }) + } + + const key = signal<[string]>(['ngOnInitTest']) + const rendered = await render(TestComponent, { + bindings: [inputBinding('key', key.asReadonly())], + detectChangesOnRender: false, + }) + rendered.fixture.detectChanges() + + const fixture = rendered.fixture + expect(spy).toHaveBeenCalled() + + const instance = fixture.componentInstance + expect(instance.initialStatus).toEqual('pending') + }) + + it('should update query data synchronously when query data changes', () => { + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['test'], + initialData: 'initial data', + })), + ) + + TestBed.tick() + + expect(query.data()).toBe('initial data') + queryClient.setQueryData(['test'], 'new data') + expect(query.data()).toBe('new data') + }) + + it('should pause fetching while restoring and fetch once restoring is disabled', async () => { + const isRestoring = signal(true) + const fetchSpy = vi.fn(() => sleep(10).then(() => 'restored-data')) + + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + provideIsRestoring(() => isRestoring.asReadonly()), + ], + }) + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectQuery(() => ({ + queryKey: ['restoring'], + queryFn: fetchSpy, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + + const query = fixture.componentInstance.query + expect(fetchSpy).not.toHaveBeenCalled() + expect(query.status()).toBe('pending') + + const stablePromise = fixture.whenStable() + await Promise.resolve() + await stablePromise + + isRestoring.set(false) + fixture.detectChanges() + + await vi.advanceTimersByTimeAsync(11) + await fixture.whenStable() + + expect(fetchSpy).toHaveBeenCalledTimes(1) + expect(query.status()).toBe('success') + expect(query.data()).toBe('restored-data') + + const cachedQuery = queryClient + .getQueryCache() + .find({ queryKey: ['restoring'] })! + expect(cachedQuery.getObserversCount()).toBe(1) + + isRestoring.set(true) + fixture.detectChanges() + expect(cachedQuery.getObserversCount()).toBe(0) + + isRestoring.set(false) + fixture.detectChanges() + expect(cachedQuery.getObserversCount()).toBe(1) + + fixture.destroy() + expect(cachedQuery.getObserversCount()).toBe(0) + }) + + it.each(['options-first', 'restoring-first'] as const)( + 'uses the latest options when leaving restoration in the same turn (%s)', + async (writeOrder) => { + const isRestoring = signal(true) + const key = signal('old') + const queriedKeys: Array = [] + + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + provideIsRestoring(() => isRestoring.asReadonly()), + ], + }) + + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['same-turn-restoration', key()], + queryFn: ({ queryKey: currentQueryKey }) => { + const currentKey = currentQueryKey[1] as string + queriedKeys.push(currentKey) + return Promise.resolve(currentKey) + }, + })), + ) + + expect(query.status()).toBe('pending') + expect(queriedKeys).toEqual([]) + + if (writeOrder === 'options-first') { + key.set('new') + isRestoring.set(false) + } else { + isRestoring.set(false) + key.set('new') + } + TestBed.tick() + const stablePromise = TestBed.inject(ApplicationRef).whenStable() + await vi.advanceTimersByTimeAsync(0) + await stablePromise + + expect(queriedKeys).toEqual(['new']) + expect(query.data()).toBe('new') + expect( + queryClient + .getQueryCache() + .find({ queryKey: ['same-turn-restoration', 'old'] })?.state + .fetchStatus, + ).toBe('idle') + expect( + queryClient + .getQueryCache() + .find({ queryKey: ['same-turn-restoration', 'new'] }) + ?.getObserversCount(), + ).toBe(1) + }, + ) + + it('allows a cache listener to read the result during restoration-boundary configuration', () => { + const isRestoring = signal(true) + const key = signal('old') + + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + provideIsRestoring(() => isRestoring.asReadonly()), + ], + }) + + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['restoration-reentrant', key()], + queryFn: () => 'data', + enabled: false, + })), + ) + + expect(query.status()).toBe('pending') + TestBed.tick() + + const boundaryRead = vi.fn(() => query.status()) + const unsubscribe = queryCache.subscribe((event) => { + if ( + event.type === 'observerOptionsUpdated' && + event.query.getObserversCount() === 0 + ) { + boundaryRead() + } + }) + + key.set('new') + isRestoring.set(false) + + expect(() => TestBed.tick()).not.toThrow() + expect(boundaryRead).toHaveBeenCalled() + expect( + queryCache + .find({ queryKey: ['restoration-reentrant', 'new'] }) + ?.getObserversCount(), + ).toBe(1) + + unsubscribe() + }) + + it('converges to the current query after an early restoration read', async () => { + const isRestoring = signal(true) + const key = signal('old') + const queriedKeys: Array = [] + const oldQueryKey = ['early-restoration-read', 'old'] as const + const newQueryKey = ['early-restoration-read', 'new'] as const + + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + provideIsRestoring(() => isRestoring.asReadonly()), + ], + }) + + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['early-restoration-read', key()], + queryFn: ({ queryKey: currentQueryKey }) => { + const currentKey = currentQueryKey[1] as string + queriedKeys.push(currentKey) + return Promise.resolve(currentKey) + }, + staleTime: Infinity, + })), + ) + + expect(query.status()).toBe('pending') + TestBed.tick() + const oldQuery = queryCache.find({ queryKey: oldQueryKey })! + expect(oldQuery.getObserversCount()).toBe(0) + + key.set('new') + isRestoring.set(false) + + // Pull before the option-configuration effect gets a chance to run. + expect(query.status()).toBe('pending') + expect(queryCache.find({ queryKey: newQueryKey })).toBeDefined() + + // A cache write to the optimistic query is adopted after configuration. + queryClient.setQueryData(newQueryKey, 'early data') + const newQuery = queryCache.find({ queryKey: newQueryKey })! + expect(newQuery.getObserversCount()).toBe(0) + TestBed.tick() + const stablePromise = TestBed.inject(ApplicationRef).whenStable() + await vi.advanceTimersByTimeAsync(0) + await stablePromise + + expect(oldQuery.getObserversCount()).toBe(0) + expect(newQuery.getObserversCount()).toBe(1) + expect(queriedKeys).not.toContain('new') + expect(query.data()).toBe('early data') + }) + + it('reads optimistic options before moving the subscription on the next tick', () => { + const key = signal('old') + const oldQueryKey = ['early-options-read', 'old'] as const + const newQueryKey = ['early-options-read', 'new'] as const + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['early-options-read', key()], + queryFn: () => 'unused', + enabled: false, + })), + ) + + expect(query.status()).toBe('pending') + TestBed.tick() + const oldQuery = queryCache.find({ queryKey: oldQueryKey })! + expect(oldQuery.getObserversCount()).toBe(1) + + key.set('new') + + expect(query.status()).toBe('pending') + // An existing observer stays attached until the configuration effect can + // move it atomically. + expect(oldQuery.getObserversCount()).toBe(1) + expect(queryCache.find({ queryKey: newQueryKey })).toBeDefined() + + queryClient.setQueryData(newQueryKey, 'early data') + const newQuery = queryCache.find({ queryKey: newQueryKey })! + expect(newQuery.getObserversCount()).toBe(0) + TestBed.tick() + + expect(oldQuery.getObserversCount()).toBe(0) + expect(newQuery.getObserversCount()).toBe(1) + expect(query.data()).toBe('early data') + }) + + describe('injection context', () => { + it('throws NG0203 with descriptive error outside injection context', () => { + expect(() => { + injectQuery(() => ({ + queryKey: ['injectionContextError'], + queryFn: () => sleep(0).then(() => 'Some data'), + })) + }).toThrowError(/NG0203(.*?)injectQuery/) + }) + + + it('should complete queries before whenStable() resolves', async () => { + const app = TestBed.inject(ApplicationRef) + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectQuery(() => ({ + queryKey: ['pendingTasksTest'], + queryFn: async () => { + await sleep(50) + return 'test data' + }, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + expect(query.status()).toBe('pending') + expect(query.data()).toBeUndefined() + + await vi.advanceTimersByTimeAsync(60) + await app.whenStable() + + expect(query.status()).toBe('success') + expect(query.data()).toBe('test data') + }) + + it('should complete HttpClient-based queries before whenStable() resolves', async () => { + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + provideHttpClient(), + provideHttpClientTesting(), + ], + }) + + const app = TestBed.inject(ApplicationRef) + const httpClient = TestBed.inject(HttpClient) + const httpTestingController = TestBed.inject(HttpTestingController) + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + httpClient = httpClient + query = injectQuery(() => ({ + queryKey: ['httpClientTest'], + queryFn: () => + lastValueFrom( + this.httpClient.get<{ message: string }>('/api/test'), + ), + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + setTimeout(() => { + const req = httpTestingController.expectOne('/api/test') + req.flush({ message: 'http test data' }) + }, 10) + + expect(query.status()).toBe('pending') + + // Advance timers and wait for Angular to be "stable" + await vi.advanceTimersByTimeAsync(20) + await app.whenStable() + + // Query should be complete after whenStable() thanks to PendingTasks integration + expect(query.status()).toBe('success') + expect(query.data()).toEqual({ message: 'http test data' }) + + httpTestingController.verify() + }) + + it('should handle synchronous queryFn with staleTime', async () => { + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + + const app = TestBed.inject(ApplicationRef) + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + callCount = 0 + query = injectQuery(() => ({ + queryKey: ['sync-stale'], + staleTime: 1000, + queryFn: () => { + this.callCount++ + return `sync-data-${this.callCount}` + }, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const component = fixture.componentInstance + const query = component.query + + const stablePromise = app.whenStable() + await vi.advanceTimersToNextTimerAsync() + await stablePromise + + expect(query.status()).toBe('success') + expect(query.data()).toBe('sync-data-1') + expect(component.callCount).toBe(1) + + await query.refetch() + await Promise.resolve() + await vi.runAllTimersAsync() + await app.whenStable() + + expect(query.status()).toBe('success') + expect(query.data()).toBe('sync-data-2') + expect(component.callCount).toBe(2) + }) + + it('should handle enabled/disabled transitions with synchronous queryFn', async () => { + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + + const app = TestBed.inject(ApplicationRef) + const enabledSignal = signal(false) + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + enabledSignal = enabledSignal + callCount = 0 + query = injectQuery(() => ({ + queryKey: ['sync-enabled'], + enabled: this.enabledSignal(), + queryFn: () => { + this.callCount++ + return `sync-data-${this.callCount}` + }, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const component = fixture.componentInstance + const query = component.query + + await vi.advanceTimersByTimeAsync(0) + await app.whenStable() + expect(query.status()).toBe('pending') + expect(query.data()).toBeUndefined() + expect(component.callCount).toBe(0) + + enabledSignal.set(true) + fixture.detectChanges() + + const stablePromise = app.whenStable() + await vi.advanceTimersToNextTimerAsync() + await stablePromise + + expect(query.status()).toBe('success') + expect(query.data()).toBe('sync-data-1') + expect(component.callCount).toBe(1) + }) + + it('should handle query invalidation with synchronous data', async () => { + vi.useRealTimers() + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + + const app = TestBed.inject(ApplicationRef) + const testKey = ['sync-invalidate'] + + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + callCount = 0 + query = injectQuery(() => ({ + queryKey: testKey, + queryFn: () => { + this.callCount++ + return `sync-data-${this.callCount}` + }, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const component = fixture.componentInstance + const query = component.query + + await app.whenStable() + + expect(query.status()).toBe('success') + expect(query.data()).toBe('sync-data-1') + expect(component.callCount).toBe(1) + + await queryClient.invalidateQueries({ queryKey: testKey }) + await app.whenStable() + expect(query.status()).toBe('success') + expect(query.data()).toBe('sync-data-2') + expect(component.callCount).toBe(2) + }) + + it('should keep the application unstable while invalidation is pending', async () => { + vi.useRealTimers() + let resolveRefetch!: (value: string) => void + let callCount = 0 + + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['pending-invalidation'], + queryFn: () => { + callCount++ + + if (callCount === 1) { + return 'data-1' + } + + return new Promise((resolve) => { + resolveRefetch = resolve + }) + }, + })), + ) + + const app = TestBed.inject(ApplicationRef) + await app.whenStable() + + const invalidation = queryClient.invalidateQueries({ + queryKey: ['pending-invalidation'], + }) + const stable = app.whenStable() + let stableResolved = false + void stable.then(() => { + stableResolved = true + }) + + expect(stableResolved).toBe(false) + + resolveRefetch('data-2') + + await invalidation + await stable + + expect(query.data()).toBe('data-2') + expect(query.fetchStatus()).toBe('idle') + }) + }) +}) diff --git a/packages/angular-query-experimental/src/__tests__/mutation-options.test-d.ts b/packages/angular-query/src/__tests__/mutation-options.test-d.ts similarity index 98% rename from packages/angular-query-experimental/src/__tests__/mutation-options.test-d.ts rename to packages/angular-query/src/__tests__/mutation-options.test-d.ts index 9df834a6b56..141def39454 100644 --- a/packages/angular-query-experimental/src/__tests__/mutation-options.test-d.ts +++ b/packages/angular-query/src/__tests__/mutation-options.test-d.ts @@ -176,7 +176,7 @@ describe('mutationOptions', () => { it('should infer types when used with injectIsMutating', () => { const key = queryKey() - const isMutating = injectIsMutating( + const isMutating = injectIsMutating(() => mutationOptions({ mutationKey: key, mutationFn: () => Promise.resolve(5), @@ -184,8 +184,8 @@ describe('mutationOptions', () => { ) expectTypeOf(isMutating()).toEqualTypeOf() - injectIsMutating( - // @ts-expect-error filters should have mutationKey + // @ts-expect-error filters should have mutationKey + injectIsMutating(() => mutationOptions({ mutationFn: () => Promise.resolve(5), }), diff --git a/packages/angular-query-experimental/src/__tests__/mutation-options.test.ts b/packages/angular-query/src/__tests__/mutation-options.test.ts similarity index 84% rename from packages/angular-query-experimental/src/__tests__/mutation-options.test.ts rename to packages/angular-query/src/__tests__/mutation-options.test.ts index 538e353852b..6ed633f6ea0 100644 --- a/packages/angular-query-experimental/src/__tests__/mutation-options.test.ts +++ b/packages/angular-query/src/__tests__/mutation-options.test.ts @@ -1,5 +1,5 @@ +import { Component } from '@angular/core' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { provideZonelessChangeDetection } from '@angular/core' import { TestBed } from '@angular/core/testing' import { QueryClient } from '@tanstack/query-core' import { queryKey, sleep } from '@tanstack/query-test-utils' @@ -10,6 +10,7 @@ import { mutationOptions, provideTanStackQuery, } from '..' +import { provideAngularQueryChangeDetection } from './test-utils' import type { CreateMutationOptions } from '../types' describe('mutationOptions', () => { @@ -20,8 +21,8 @@ describe('mutationOptions', () => { queryClient = new QueryClient() TestBed.configureTestingModule({ providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), ], }) }) @@ -55,15 +56,19 @@ describe('mutationOptions', () => { mutationFn: () => sleep(50).then(() => 'data'), }) - const [mutation, isMutating] = TestBed.runInInjectionContext(() => [ - injectMutation(() => mutationOpts), - injectIsMutating(), - ]) + @Component({ template: '' }) + class Host { + readonly mutation = injectMutation(() => mutationOpts) + readonly isMutating = injectIsMutating() + } + const fixture = TestBed.createComponent(Host) + fixture.detectChanges() + const { mutation, isMutating } = fixture.componentInstance expect(isMutating()).toBe(0) mutation.mutate() - expect(isMutating()).toBe(0) + expect(isMutating()).toBe(1) await vi.advanceTimersByTimeAsync(0) expect(isMutating()).toBe(1) await vi.advanceTimersByTimeAsync(51) @@ -75,15 +80,19 @@ describe('mutationOptions', () => { mutationFn: () => sleep(50).then(() => 'data'), }) - const [mutation, isMutating] = TestBed.runInInjectionContext(() => [ - injectMutation(() => mutationOpts), - injectIsMutating(), - ]) + @Component({ template: '' }) + class Host { + readonly mutation = injectMutation(() => mutationOpts) + readonly isMutating = injectIsMutating() + } + const fixture = TestBed.createComponent(Host) + fixture.detectChanges() + const { mutation, isMutating } = fixture.componentInstance expect(isMutating()).toBe(0) mutation.mutate() - expect(isMutating()).toBe(0) + expect(isMutating()).toBe(1) await vi.advanceTimersByTimeAsync(0) expect(isMutating()).toBe(1) await vi.advanceTimersByTimeAsync(51) @@ -100,19 +109,21 @@ describe('mutationOptions', () => { mutationFn: () => sleep(50).then(() => 'data2'), }) - const [mutation1, mutation2, isMutating] = TestBed.runInInjectionContext( - () => [ - injectMutation(() => mutationOpts1), - injectMutation(() => mutationOpts2), - injectIsMutating(), - ], - ) + @Component({ template: '' }) + class Host { + readonly mutation1 = injectMutation(() => mutationOpts1) + readonly mutation2 = injectMutation(() => mutationOpts2) + readonly isMutating = injectIsMutating() + } + const fixture = TestBed.createComponent(Host) + fixture.detectChanges() + const { mutation1, mutation2, isMutating } = fixture.componentInstance expect(isMutating()).toBe(0) mutation1.mutate() mutation2.mutate() - expect(isMutating()).toBe(0) + expect(isMutating()).toBe(2) await vi.advanceTimersByTimeAsync(0) expect(isMutating()).toBe(2) await vi.advanceTimersByTimeAsync(51) @@ -129,19 +140,23 @@ describe('mutationOptions', () => { mutationFn: () => sleep(50).then(() => 'data2'), }) - const [mutation1, mutation2, isMutating] = TestBed.runInInjectionContext( - () => [ - injectMutation(() => mutationOpts1), - injectMutation(() => mutationOpts2), - injectIsMutating({ mutationKey: mutationOpts1.mutationKey }), - ], - ) + @Component({ template: '' }) + class Host { + readonly mutation1 = injectMutation(() => mutationOpts1) + readonly mutation2 = injectMutation(() => mutationOpts2) + readonly isMutating = injectIsMutating(() => ({ + mutationKey: mutationOpts1.mutationKey, + })) + } + const fixture = TestBed.createComponent(Host) + fixture.detectChanges() + const { mutation1, mutation2, isMutating } = fixture.componentInstance expect(isMutating()).toBe(0) mutation1.mutate() mutation2.mutate() - expect(isMutating()).toBe(0) + expect(isMutating()).toBe(1) await vi.advanceTimersByTimeAsync(0) expect(isMutating()).toBe(1) await vi.advanceTimersByTimeAsync(51) diff --git a/packages/angular-query/src/__tests__/pending-tasks-ssr.test.ts b/packages/angular-query/src/__tests__/pending-tasks-ssr.test.ts new file mode 100644 index 00000000000..30db5a70f09 --- /dev/null +++ b/packages/angular-query/src/__tests__/pending-tasks-ssr.test.ts @@ -0,0 +1,128 @@ +import { + ChangeDetectionStrategy, + Component, + destroyPlatform, + provideZonelessChangeDetection, +} from '@angular/core' +import { bootstrapApplication } from '@angular/platform-browser' +import { + provideServerRendering, + renderApplication, +} from '@angular/platform-server' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { sleep } from '@tanstack/query-test-utils' +import { + QueryClient, + injectQueries, + injectQuery, + provideTanStackQuery, +} from '..' + +describe('PendingTasks SSR', () => { + beforeEach(() => { + destroyPlatform() + vi.useFakeTimers() + }) + + afterEach(() => { + vi.useRealTimers() + }) + + @Component({ + selector: 'app-root', + template: '{{ query.data() }}', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestInjectQueryComponent { + query = injectQuery(() => ({ + queryKey: ['ssr-test'], + queryFn: async () => { + await sleep(1000) + return 'data-fetched-on-ssr' + }, + })) + } + + @Component({ + selector: 'app-queries-root', + template: '{{ queries()[0].data() }}', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestInjectQueriesComponent { + queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['ssr-queries-test'], + queryFn: async () => { + await sleep(1000) + return 'queries-data-fetched-on-ssr' + }, + }, + ], + })) + } + + it('should wait for stability of injectQuery', async () => { + const htmlPromise = renderApplication( + (context) => + bootstrapApplication( + TestInjectQueryComponent, + { + providers: [ + provideServerRendering(), + provideZonelessChangeDetection(), + provideTanStackQuery( + () => + new QueryClient({ + defaultOptions: { queries: { retry: false } }, + }), + ), + ], + }, + context, + ), + { + url: '/', + document: + '', + }, + ) + + await vi.runAllTimersAsync() + const html = await htmlPromise + + expect(html).toContain('data-fetched-on-ssr') + }) + + it('should wait for stability of injectQueries', async () => { + const htmlPromise = renderApplication( + (context) => + bootstrapApplication( + TestInjectQueriesComponent, + { + providers: [ + provideServerRendering(), + provideZonelessChangeDetection(), + provideTanStackQuery( + () => + new QueryClient({ + defaultOptions: { queries: { retry: false } }, + }), + ), + ], + }, + context, + ), + { + url: '/', + document: + '', + }, + ) + + await vi.runAllTimersAsync() + const html = await htmlPromise + + expect(html).toContain('queries-data-fetched-on-ssr') + }) +}) diff --git a/packages/angular-query/src/__tests__/pending-tasks-ssr.zoneful.test.ts b/packages/angular-query/src/__tests__/pending-tasks-ssr.zoneful.test.ts new file mode 100644 index 00000000000..a18632811d5 --- /dev/null +++ b/packages/angular-query/src/__tests__/pending-tasks-ssr.zoneful.test.ts @@ -0,0 +1,155 @@ +import { + ChangeDetectionStrategy, + Component, + destroyPlatform, + provideZoneChangeDetection, + signal, +} from '@angular/core' +import { bootstrapApplication } from '@angular/platform-browser' +import { + provideServerRendering, + renderApplication, +} from '@angular/platform-server' +import { afterEach, describe, expect, it } from 'vitest' +import { + QueryClient, + injectQueries, + injectQuery, + provideTanStackQuery, +} from '..' +import type { ApplicationRef, Type } from '@angular/core' + +const fetchData = () => + new Promise((resolve) => { + setTimeout(() => resolve('fetched-on-server'), 20) + }) + +@Component({ + selector: 'app-root', + template: '{{ query.data() }}', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +class CachedQueryComponent { + readonly query = injectQuery(() => ({ + queryKey: ['cached'], + initialData: 'cached-on-server', + queryFn: fetchData, + staleTime: 30_000, + gcTime: 24 * 60 * 60 * 1000, + })) +} + +@Component({ + selector: 'app-root', + template: '{{ query.data() }}', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +class FetchingQueryComponent { + readonly query = injectQuery(() => ({ + queryKey: ['fetching'], + queryFn: fetchData, + staleTime: 30_000, + gcTime: 24 * 60 * 60 * 1000, + })) +} + +@Component({ + selector: 'app-root', + template: '{{ queries()[0].data() }}', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +class FetchingQueriesComponent { + readonly queries = injectQueries(() => ({ + queries: [ + { + queryKey: ['parallel'], + queryFn: fetchData, + staleTime: 30_000, + gcTime: 24 * 60 * 60 * 1000, + }, + ], + })) +} + +@Component({ + selector: 'app-root', + template: '{{ query.data() }}', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +class ReactiveQueryComponent { + readonly key = signal('first') + readonly query = injectQuery(() => ({ + queryKey: [this.key()], + initialData: this.key(), + queryFn: fetchData, + staleTime: 30_000, + gcTime: 24 * 60 * 60 * 1000, + })) + + ngOnInit() { + setTimeout(() => this.key.set('second'), 20) + } +} + +async function render(component: Type) { + const client = new QueryClient() + let app: ApplicationRef | undefined + let deadline: ReturnType | undefined + try { + return await Promise.race([ + renderApplication( + async (context) => { + app = await bootstrapApplication( + component, + { + providers: [ + provideServerRendering(), + provideZoneChangeDetection(), + provideTanStackQuery(() => client), + ], + }, + context, + ) + return app + }, + { + url: '/', + document: '', + }, + ), + new Promise((_, reject) => { + deadline = setTimeout( + () => + reject(new Error('SSR did not become stable within one second')), + 1000, + ) + }), + ]) + } finally { + clearTimeout(deadline) + if (app && !app.destroyed) app.destroy() + client.clear() + } +} + +describe('SSR with real Zone.js timers', () => { + afterEach(() => destroyPlatform()) + + it('serializes cached data without waiting for stale or GC timers', async () => { + expect(await render(CachedQueryComponent)).toContain('cached-on-server') + }) + + it('serializes reactive query changes without waiting for background timers', async () => { + expect(await render(ReactiveQueryComponent)).toContain('second') + }) + + it('waits for a query fetch, but not its background timers', async () => { + expect(await render(FetchingQueryComponent)).toContain('fetched-on-server') + }) + + it('waits for parallel query fetches, but not their background timers', async () => { + expect(await render(FetchingQueriesComponent)).toContain( + 'fetched-on-server', + ) + }) +}) diff --git a/packages/angular-query-experimental/src/__tests__/pending-tasks.test.ts b/packages/angular-query/src/__tests__/pending-tasks.test.ts similarity index 62% rename from packages/angular-query-experimental/src/__tests__/pending-tasks.test.ts rename to packages/angular-query/src/__tests__/pending-tasks.test.ts index c5a1f58d81f..74f8e1b5f09 100644 --- a/packages/angular-query-experimental/src/__tests__/pending-tasks.test.ts +++ b/packages/angular-query/src/__tests__/pending-tasks.test.ts @@ -1,7 +1,7 @@ import { ApplicationRef, + ChangeDetectionStrategy, Component, - provideZonelessChangeDetection, } from '@angular/core' import { TestBed } from '@angular/core/testing' import { HttpClient, provideHttpClient } from '@angular/common/http' @@ -10,15 +10,16 @@ import { provideHttpClientTesting, } from '@angular/common/http/testing' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { queryKey, sleep } from '@tanstack/query-test-utils' +import { sleep } from '@tanstack/query-test-utils' import { lastValueFrom } from 'rxjs' import { QueryClient, injectMutation, injectQuery, onlineManager, - provideTanStackQuery, + skipToken, } from '..' +import { flushQueryUpdates, setupTanStackQueryTestBed } from './test-utils' describe('PendingTasks Integration', () => { let queryClient: QueryClient @@ -37,12 +38,7 @@ describe('PendingTasks Integration', () => { }, }) - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), - ], - }) + setupTanStackQueryTestBed(queryClient) }) afterEach(() => { @@ -51,17 +47,58 @@ describe('PendingTasks Integration', () => { vi.useRealTimers() }) + it.each([false, true])( + 'keeps all mutation invocations pending (reset=%s)', + async (reset) => { + vi.useRealTimers() + const resolve = new Map void>() + const mutation = TestBed.runInInjectionContext(() => + injectMutation(() => ({ + mutationFn: (id: string) => + new Promise((done) => resolve.set(id, done)), + })), + ) + const first = mutation.mutateAsync('first') + const second = mutation.mutateAsync('second') + await Promise.resolve() + if (reset) mutation.reset() + let stable = false + const stability = TestBed.inject(ApplicationRef) + .whenStable() + .then(() => { + stable = true + }) + resolve.get('second')!('second') + await second + await Promise.resolve() + expect(stable).toBe(false) + expect(queryClient.isMutating()).toBe(1) + resolve.get('first')!('first') + await first + await stability + expect(stable).toBe(true) + }, + ) + describe('Synchronous Resolution', () => { it('should handle synchronous queryFn with whenStable()', async () => { const app = TestBed.inject(ApplicationRef) - const key = queryKey() - const query = TestBed.runInInjectionContext(() => - injectQuery(() => ({ - queryKey: key, - queryFn: () => 'instant-data', // Resolves synchronously - })), - ) + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectQuery(() => ({ + queryKey: ['sync'], + queryFn: () => 'instant-data', + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query // Should start as pending even with synchronous data expect(query.status()).toBe('pending') @@ -73,7 +110,6 @@ describe('PendingTasks Integration', () => { await vi.advanceTimersByTimeAsync(10) await stablePromise - // Should work correctly even though queryFn was synchronous expect(query.status()).toBe('success') expect(query.data()).toBe('instant-data') }) @@ -81,13 +117,12 @@ describe('PendingTasks Integration', () => { it('should handle synchronous error with whenStable()', async () => { const app = TestBed.inject(ApplicationRef) - const key = queryKey() const query = TestBed.runInInjectionContext(() => injectQuery(() => ({ - queryKey: key, + queryKey: ['sync-error'], queryFn: () => { throw new Error('instant-error') - }, // Throws synchronously + }, })), ) @@ -142,7 +177,6 @@ describe('PendingTasks Integration', () => { ) mutation.mutate() - TestBed.tick() const stablePromise = app.whenStable() @@ -153,11 +187,95 @@ describe('PendingTasks Integration', () => { expect(mutation.isError()).toBe(true) expect(mutation.error()).toEqual(new Error('sync-mutation-error')) }) + + it('should keep whenStable pending after mutate starts', async () => { + const app = TestBed.inject(ApplicationRef) + + const mutation = TestBed.runInInjectionContext(() => + injectMutation(() => ({ + mutationFn: async () => { + await sleep(20) + return 'done' + }, + })), + ) + + mutation.mutate() + + let stableResolved = false + const stablePromise = app.whenStable().then(() => { + stableResolved = true + }) + + await Promise.resolve() + expect(stableResolved).toBe(false) + + await vi.advanceTimersByTimeAsync(21) + await vi.advanceTimersByTimeAsync(0) + await stablePromise + expect(mutation.isSuccess()).toBe(true) + expect(mutation.data()).toBe('done') + }) }) describe('Race Conditions', () => { + it('should not register a pending task while query is disabled by enabled', async () => { + const queryFn = vi.fn(async () => { + await sleep(10) + return 'disabled-data' + }) + + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectQuery(() => ({ + queryKey: ['disabled-enabled'], + queryFn, + enabled: false, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + await Promise.resolve() + + expect(query.status()).toBe('pending') + expect(query.fetchStatus()).toBe('idle') + expect(query.isPending()).toBe(true) + expect(queryFn).not.toHaveBeenCalled() + expect(fixture.isStable()).toBe(true) + }) + + it('should not register a pending task while query is disabled by skipToken', async () => { + @Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query = injectQuery(() => ({ + queryKey: ['disabled-skip-token'], + queryFn: skipToken, + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query + + await Promise.resolve() + + expect(query.status()).toBe('pending') + expect(query.fetchStatus()).toBe('idle') + expect(query.isPending()).toBe(true) + expect(query.isEnabled()).toBe(false) + expect(fixture.isStable()).toBe(true) + }) + it('should handle query that completes during initial subscription', async () => { - const key = queryKey() const app = TestBed.inject(ApplicationRef) let resolveQuery: (value: string) => void @@ -167,7 +285,7 @@ describe('PendingTasks Integration', () => { const query = TestBed.runInInjectionContext(() => injectQuery(() => ({ - queryKey: key, + queryKey: ['race-condition'], queryFn: () => queryPromise, })), ) @@ -186,19 +304,27 @@ describe('PendingTasks Integration', () => { it('should handle rapid refetches without task leaks', async () => { const app = TestBed.inject(ApplicationRef) - let callCount = 0 - const key = queryKey() - const query = TestBed.runInInjectionContext(() => - injectQuery(() => ({ - queryKey: key, + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + callCount = 0 + query = injectQuery(() => ({ + queryKey: ['rapid-refetch'], queryFn: async () => { - callCount++ + this.callCount++ await sleep(10) - return `data-${callCount}` + return `data-${this.callCount}` }, - })), - ) + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const query = fixture.componentInstance.query // Trigger multiple rapid refetches query.refetch() @@ -213,14 +339,61 @@ describe('PendingTasks Integration', () => { expect(query.data()).toMatch(/^data-\d+$/) }) + it('should keep PendingTasks active when query starts offline (never reaches fetching)', async () => { + const app = TestBed.inject(ApplicationRef) + + onlineManager.setOnline(false) + + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['start-offline'], + networkMode: 'online', // Default: won't fetch while offline + queryFn: async () => { + await sleep(10) + return 'online-data' + }, + })), + ) + + // Allow query to initialize + await Promise.resolve() + await flushQueryUpdates() + + // Query should initialize directly to 'paused' (never goes through 'fetching') + expect(query.status()).toBe('pending') + expect(query.fetchStatus()).toBe('paused') + + const stablePromise = app.whenStable() + let stableResolved = false + void stablePromise.then(() => { + stableResolved = true + }) + + await Promise.resolve() + + // PendingTasks should block stability even though we never hit 'fetching' + expect(stableResolved).toBe(false) + + // Bring the app back online so the query can fetch + onlineManager.setOnline(true) + + await vi.advanceTimersByTimeAsync(20) + await Promise.resolve() + + await stablePromise + + expect(stableResolved).toBe(true) + expect(query.status()).toBe('success') + expect(query.data()).toBe('online-data') + }) + it('should keep PendingTasks active while query retry is paused offline', async () => { const app = TestBed.inject(ApplicationRef) let attempt = 0 - const key = queryKey() const query = TestBed.runInInjectionContext(() => injectQuery(() => ({ - queryKey: key, + queryKey: ['paused-offline'], retry: 1, retryDelay: 50, // Longer delay to ensure we can go offline before retry queryFn: async () => { @@ -235,7 +408,7 @@ describe('PendingTasks Integration', () => { ) // Allow the initial attempt to start and fail - await vi.advanceTimersByTimeAsync(0) + await flushQueryUpdates() await Promise.resolve() // Wait for the first attempt to complete and start retry delay @@ -282,84 +455,97 @@ describe('PendingTasks Integration', () => { }) describe('Component Destruction', () => { - @Component({ - template: '', - }) - class TestComponent { - query = injectQuery(() => ({ - queryKey: ['component-query'], - queryFn: () => sleep(100).then(() => 'component-data'), - })) - - mutation = injectMutation(() => ({ - mutationFn: (data: string) => - sleep(100).then(() => `processed: ${data}`), - })) - } - - it('should cleanup pending tasks when component with active query is destroyed', async () => { - const app = TestBed.inject(ApplicationRef) - const fixture = TestBed.createComponent(TestComponent) + it('becomes stable after destruction before an unresolved query completes', async () => { + vi.useRealTimers() + let resolveQuery!: (value: string) => void + const queryPromise = new Promise((resolve) => { + resolveQuery = resolve + }) - // Start the query - expect(fixture.componentInstance.query.status()).toBe('pending') + @Component({ template: '' }) + class UnresolvedQueryComponent { + query = injectQuery(() => ({ + queryKey: ['unresolved-component-query'], + queryFn: () => queryPromise, + })) + } - // Destroy component while query is running - fixture.destroy() + const fixture = TestBed.createComponent(UnresolvedQueryComponent) + fixture.detectChanges() + expect(fixture.isStable()).toBe(false) - // Angular should become stable even though component was destroyed - const stablePromise = app.whenStable() - await vi.advanceTimersByTimeAsync(150) + fixture.destroy() + await fixture.whenStable() + expect(fixture.isStable()).toBe(true) - await expect(stablePromise).resolves.toEqual(undefined) + resolveQuery('eventual data') + await Promise.resolve() }) - it('should cleanup pending tasks when component with active mutation is destroyed', async () => { - const app = TestBed.inject(ApplicationRef) - const fixture = TestBed.createComponent(TestComponent) + it('becomes stable after destruction before an unresolved mutation completes', async () => { + vi.useRealTimers() + let resolveMutation!: (value: string) => void + const mutationPromise = new Promise((resolve) => { + resolveMutation = resolve + }) - fixture.componentInstance.mutation.mutate('test') + @Component({ template: '' }) + class UnresolvedMutationComponent { + mutation = injectMutation(() => ({ + mutationFn: () => mutationPromise, + })) + } - // Destroy component while mutation is running - fixture.destroy() + const fixture = TestBed.createComponent(UnresolvedMutationComponent) + fixture.detectChanges() + fixture.componentInstance.mutation.mutate() + expect(fixture.isStable()).toBe(false) - // Angular should become stable even though component was destroyed - const stablePromise = app.whenStable() - await vi.advanceTimersByTimeAsync(150) + fixture.destroy() + await fixture.whenStable() + expect(fixture.isStable()).toBe(true) - await expect(stablePromise).resolves.toEqual(undefined) + resolveMutation('eventual data') + await Promise.resolve() }) }) describe('Concurrent Operations', () => { it('should handle multiple queries running simultaneously', async () => { - const key1 = queryKey() - const key2 = queryKey() - const key3 = queryKey() const app = TestBed.inject(ApplicationRef) - const query1 = TestBed.runInInjectionContext(() => - injectQuery(() => ({ - queryKey: key1, - queryFn: () => sleep(30).then(() => 'data-1'), - })), - ) + @Component({ + selector: 'app-test', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + query1 = injectQuery(() => ({ + queryKey: ['concurrent-1'], + queryFn: async () => { + await sleep(30) + return 'data-1' + }, + })) - const query2 = TestBed.runInInjectionContext(() => - injectQuery(() => ({ - queryKey: key2, - queryFn: () => sleep(50).then(() => 'data-2'), - })), - ) + query2 = injectQuery(() => ({ + queryKey: ['concurrent-2'], + queryFn: async () => { + await sleep(50) + return 'data-2' + }, + })) - const query3 = TestBed.runInInjectionContext(() => - injectQuery(() => ({ - queryKey: key3, - queryFn: () => 'instant-data', // Synchronous - })), - ) + query3 = injectQuery(() => ({ + queryKey: ['concurrent-3'], + queryFn: () => 'instant-data', + })) + } + + const fixture = TestBed.createComponent(TestComponent) + fixture.detectChanges() + const { query1, query2, query3 } = fixture.componentInstance - // All queries should start expect(query1.status()).toBe('pending') expect(query2.status()).toBe('pending') expect(query3.status()).toBe('pending') @@ -368,7 +554,6 @@ describe('PendingTasks Integration', () => { await vi.advanceTimersByTimeAsync(60) await stablePromise - // All queries should be complete expect(query1.status()).toBe('success') expect(query1.data()).toBe('data-1') expect(query2.status()).toBe('success') @@ -382,15 +567,19 @@ describe('PendingTasks Integration', () => { const mutation1 = TestBed.runInInjectionContext(() => injectMutation(() => ({ - mutationFn: (data: string) => - sleep(30).then(() => `processed-1: ${data}`), + mutationFn: async (data: string) => { + await sleep(30) + return `processed-1: ${data}` + }, })), ) const mutation2 = TestBed.runInInjectionContext(() => injectMutation(() => ({ - mutationFn: (data: string) => - sleep(50).then(() => `processed-2: ${data}`), + mutationFn: async (data: string) => { + await sleep(50) + return `processed-2: ${data}` + }, })), ) @@ -403,7 +592,6 @@ describe('PendingTasks Integration', () => { })), ) - // Start all mutations mutation1.mutate('test1') mutation2.mutate('test2') mutation3.mutate('test3') @@ -414,7 +602,6 @@ describe('PendingTasks Integration', () => { await vi.advanceTimersByTimeAsync(60) await stablePromise - // All mutations should be complete expect(mutation1.isSuccess()).toBe(true) expect(mutation1.data()).toBe('processed-1: test1') expect(mutation2.isSuccess()).toBe(true) @@ -426,29 +613,31 @@ describe('PendingTasks Integration', () => { it('should handle mixed queries and mutations', async () => { const app = TestBed.inject(ApplicationRef) - const key = queryKey() const query = TestBed.runInInjectionContext(() => injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(40).then(() => 'query-data'), + queryKey: ['mixed-query'], + queryFn: async () => { + await sleep(40) + return 'query-data' + }, })), ) const mutation = TestBed.runInInjectionContext(() => injectMutation(() => ({ - mutationFn: (data: string) => - sleep(60).then(() => `mutation: ${data}`), + mutationFn: async (data: string) => { + await sleep(60) + return `mutation: ${data}` + }, })), ) - // Start both operations mutation.mutate('test') const stablePromise = app.whenStable() await vi.advanceTimersByTimeAsync(70) await stablePromise - // Both should be complete expect(query.status()).toBe('success') expect(query.data()).toBe('query-data') expect(mutation.isSuccess()).toBe(true) @@ -458,7 +647,7 @@ describe('PendingTasks Integration', () => { describe('HttpClient Integration', () => { beforeEach(() => { - TestBed.configureTestingModule({ + setupTanStackQueryTestBed(queryClient, { providers: [provideHttpClient(), provideHttpClientTesting()], }) }) @@ -468,12 +657,9 @@ describe('PendingTasks Integration', () => { const httpClient = TestBed.inject(HttpClient) const httpTestingController = TestBed.inject(HttpTestingController) - const key1 = queryKey() - const key2 = queryKey() - const query1 = TestBed.runInInjectionContext(() => injectQuery(() => ({ - queryKey: key1, + queryKey: ['http-1'], queryFn: () => lastValueFrom(httpClient.get<{ id: number }>('/api/1')), })), @@ -481,13 +667,12 @@ describe('PendingTasks Integration', () => { const query2 = TestBed.runInInjectionContext(() => injectQuery(() => ({ - queryKey: key2, + queryKey: ['http-2'], queryFn: () => lastValueFrom(httpClient.get<{ id: number }>('/api/2')), })), ) - // Schedule HTTP responses setTimeout(() => { const req1 = httpTestingController.expectOne('/api/1') req1.flush({ id: 1 }) @@ -513,10 +698,9 @@ describe('PendingTasks Integration', () => { const httpClient = TestBed.inject(HttpClient) const httpTestingController = TestBed.inject(HttpTestingController) - const key = queryKey() const query = TestBed.runInInjectionContext(() => injectQuery(() => ({ - queryKey: key, + queryKey: ['http-cancel'], queryFn: () => lastValueFrom(httpClient.get<{ data: string }>('/api/cancel')), })), @@ -543,19 +727,21 @@ describe('PendingTasks Integration', () => { describe('Edge Cases', () => { it('should handle query cancellation mid-flight', async () => { - const key = queryKey() const app = TestBed.inject(ApplicationRef) const query = TestBed.runInInjectionContext(() => injectQuery(() => ({ - queryKey: key, - queryFn: () => sleep(100).then(() => 'data'), + queryKey: ['cancel-test'], + queryFn: async () => { + await sleep(100) + return 'data' + }, })), ) // Cancel the query after a short delay setTimeout(() => { - queryClient.cancelQueries({ queryKey: key }) + queryClient.cancelQueries({ queryKey: ['cancel-test'] }) }, 20) // Advance to the cancellation point @@ -576,10 +762,9 @@ describe('PendingTasks Integration', () => { const app = TestBed.inject(ApplicationRef) let attemptCount = 0 - const key = queryKey() const query = TestBed.runInInjectionContext(() => injectQuery(() => ({ - queryKey: key, + queryKey: ['retry-test'], retry: 2, retryDelay: 10, queryFn: async () => { @@ -603,13 +788,16 @@ describe('PendingTasks Integration', () => { it('should handle mutation with optimistic updates', async () => { const app = TestBed.inject(ApplicationRef) - const testQueryKey = queryKey() + const testQueryKey = ['optimistic-test'] queryClient.setQueryData(testQueryKey, 'initial-data') const mutation = TestBed.runInInjectionContext(() => injectMutation(() => ({ - mutationFn: (newData: string) => sleep(50).then(() => newData), + mutationFn: async (newData: string) => { + await sleep(50) + return newData + }, onMutate: async (newData) => { // Optimistic update const previousData = queryClient.getQueryData(testQueryKey) diff --git a/packages/angular-query/src/__tests__/provide-tanstack-query.test-d.ts b/packages/angular-query/src/__tests__/provide-tanstack-query.test-d.ts new file mode 100644 index 00000000000..814f624e4b8 --- /dev/null +++ b/packages/angular-query/src/__tests__/provide-tanstack-query.test-d.ts @@ -0,0 +1,44 @@ +import { describe, expectTypeOf, it } from 'vitest' +import { + QueryClient, + provideTanStackQuery, + withHydrationKey, + withNoQueryHydration, +} from '..' +import type { QueryFeature } from '..' +import type * as PublicApi from '..' +import type * as InternalApi from '../internal' + +describe('provideTanStackQuery', () => { + it('keeps integration helpers out of the public entry point', () => { + type InternalHelpers = + | 'queryFeature' + | 'getQueryFeatureProviders' + | 'provideIsRestoring' + expectTypeOf>().toBeNever() + expectTypeOf< + Extract + >().toEqualTypeOf() + }) + + it('accepts built-in opaque query features', () => { + expectTypeOf(withHydrationKey('cache')).toEqualTypeOf() + expectTypeOf(withNoQueryHydration()).toEqualTypeOf() + + provideTanStackQuery( + () => new QueryClient(), + withHydrationKey('cache'), + withNoQueryHydration(), + ) + }) + + it('rejects structurally fabricated features', () => { + expectTypeOf(withHydrationKey('cache')).toEqualTypeOf() + + provideTanStackQuery( + () => new QueryClient(), + // @ts-expect-error QueryFeature values can only be created by package features + { ɵkind: 'Hydration', ɵproviders: {} }, + ) + }) +}) diff --git a/packages/angular-query/src/__tests__/provide-tanstack-query.test.ts b/packages/angular-query/src/__tests__/provide-tanstack-query.test.ts new file mode 100644 index 00000000000..ae5fa7a7f9f --- /dev/null +++ b/packages/angular-query/src/__tests__/provide-tanstack-query.test.ts @@ -0,0 +1,79 @@ +import { TestBed } from '@angular/core/testing' +import { describe, expect, it } from 'vitest' +import { InjectionToken, PLATFORM_ID, inject } from '@angular/core' +import { QueryClient } from '@tanstack/query-core' +import { provideTanStackQuery } from '../providers' +import { provideAngularQueryChangeDetection } from './test-utils' + +describe('provideTanStackQuery', () => { + it('should provide a QueryClient instance using a factory', () => { + const queryClient = new QueryClient() + + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + + const providedQueryClient = TestBed.inject(QueryClient) + expect(providedQueryClient).toBe(queryClient) + }) + + it('resolves an existing QueryClient through a factory in the injection context', () => { + const queryClient = new QueryClient() + const CUSTOM_QUERY_CLIENT = new InjectionToken('', { + factory: () => queryClient, + }) + + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => inject(CUSTOM_QUERY_CLIENT)), + ], + }) + + const providedQueryClient = TestBed.inject(QueryClient) + expect(providedQueryClient).toBe(queryClient) + }) +}) + +describe('server client defaults', () => { + it('uses server defaults without changing an unrelated client', () => { + const unrelated = new QueryClient() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + { provide: PLATFORM_ID, useValue: 'server' }, + provideTanStackQuery(() => new QueryClient()), + ], + }) + expect(TestBed.inject(QueryClient).getDefaultOptions()).toEqual({ + queries: { gcTime: Infinity, retry: false }, + mutations: { gcTime: Infinity }, + }) + expect(unrelated.getDefaultOptions()).toEqual({}) + }) + + it('preserves explicit server client defaults', () => { + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + { provide: PLATFORM_ID, useValue: 'server' }, + provideTanStackQuery( + () => + new QueryClient({ + defaultOptions: { + queries: { gcTime: 1000, retry: 1, staleTime: 30000 }, + mutations: { gcTime: 2000 }, + }, + }), + ), + ], + }) + expect(TestBed.inject(QueryClient).getDefaultOptions()).toEqual({ + queries: { gcTime: 1000, retry: 1, staleTime: 30000 }, + mutations: { gcTime: 2000 }, + }) + }) +}) diff --git a/packages/angular-query-experimental/src/__tests__/query-options.test-d.ts b/packages/angular-query/src/__tests__/query-options.test-d.ts similarity index 100% rename from packages/angular-query-experimental/src/__tests__/query-options.test-d.ts rename to packages/angular-query/src/__tests__/query-options.test-d.ts index 830e8df805b..50d81d51889 100644 --- a/packages/angular-query-experimental/src/__tests__/query-options.test-d.ts +++ b/packages/angular-query/src/__tests__/query-options.test-d.ts @@ -174,19 +174,6 @@ it('should return the proper type when passed to getQueryData', () => { expectTypeOf(data).toEqualTypeOf() }) -it('should return the proper type when passed to getQueryState', () => { - const key = queryKey() - const { queryKey: tagged } = queryOptions({ - queryKey: key, - queryFn: () => Promise.resolve(5), - }) - - const queryClient = new QueryClient() - const state = queryClient.getQueryState(tagged) - - expectTypeOf(state?.data).toEqualTypeOf() -}) - it('should properly type updaterFn when passed to setQueryData', () => { const key = queryKey() const { queryKey: tagged } = queryOptions({ @@ -222,6 +209,19 @@ it('should properly type value when passed to setQueryData', () => { expectTypeOf(data).toEqualTypeOf() }) +it('should return the proper type when passed to getQueryState', () => { + const key = queryKey() + const { queryKey: tagged } = queryOptions({ + queryKey: key, + queryFn: () => Promise.resolve(5), + }) + + const queryClient = new QueryClient() + const state = queryClient.getQueryState(tagged) + + expectTypeOf(state?.data).toEqualTypeOf() +}) + it('should infer even if there is a conditional skipToken', () => { const key = queryKey() const options = queryOptions({ diff --git a/packages/angular-query-experimental/src/__tests__/query-options.test.ts b/packages/angular-query/src/__tests__/query-options.test.ts similarity index 58% rename from packages/angular-query-experimental/src/__tests__/query-options.test.ts rename to packages/angular-query/src/__tests__/query-options.test.ts index 72a53326326..40d5704be74 100644 --- a/packages/angular-query-experimental/src/__tests__/query-options.test.ts +++ b/packages/angular-query/src/__tests__/query-options.test.ts @@ -11,4 +11,14 @@ describe('queryOptions', () => { expect(queryOptions(object)).toBe(object) }) + + it('keeps notifyOnChangeProps adapter-owned', () => { + const options: CreateQueryOptions = { + queryKey: ['key'], + // @ts-expect-error Angular Query always subscribes to every result change. + notifyOnChangeProps: ['data'], + } + + expect(options).toHaveProperty('notifyOnChangeProps', ['data']) + }) }) diff --git a/packages/angular-query/src/__tests__/signal-proxy.test.ts b/packages/angular-query/src/__tests__/signal-proxy.test.ts new file mode 100644 index 00000000000..58b3b40cc0b --- /dev/null +++ b/packages/angular-query/src/__tests__/signal-proxy.test.ts @@ -0,0 +1,77 @@ +import { + ChangeDetectionStrategy, + Component, + computed, + input, + inputBinding, + isSignal, + signal, +} from '@angular/core' +import { beforeEach, describe, expect, it } from 'vitest' +import { TestBed } from '@angular/core/testing' +import { signalProxy } from '../utils/signal-proxy' +import { provideAngularQueryChangeDetection } from './test-utils' + +describe('signalProxy', () => { + it('only exposes declared fields with ordinary object semantics', async () => { + const source = signal({ value: 'data', falsy: false, zero: 0 }) + const proxy = signalProxy(source, ['value', 'falsy', 'zero']) + + expect(Object.keys(proxy)).toEqual(['value', 'falsy', 'zero']) + expect('value' in proxy).toBe(true) + expect('falsy' in proxy).toBe(true) + expect('zero' in proxy).toBe(true) + expect('missing' in proxy).toBe(false) + expect(Object.hasOwn(proxy, 'missing')).toBe(false) + expect(Reflect.get(proxy, 'then')).toBeUndefined() + expect(await Promise.resolve(proxy)).toBe(proxy) + }) + + it('should have computed fields', () => { + const source = signal({ value: 'data' }) + const proxy = signalProxy(source, ['value']) + expect(proxy.value()).toBe('data') + expect(isSignal(proxy.value)).toBe(true) + }) + + describe('in component fixture', () => { + @Component({ + selector: 'app-test', + standalone: true, + template: '{{ proxy.number() }}', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class TestComponent { + number = input.required() + obj = computed(() => ({ number: this.number() })) + proxy = signalProxy(this.obj, ['number']) + shortNumber = this.proxy.number + } + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [provideAngularQueryChangeDetection()], + }) + }) + + it('should retain field signals and update aliases of required inputs', () => { + const number = signal(0) + const fixture = TestBed.createComponent(TestComponent, { + bindings: [inputBinding('number', number.asReadonly())], + }) + fixture.detectChanges() + const instance = fixture.componentInstance + + expect(isSignal(instance.proxy.number)).toBe(true) + expect(instance.shortNumber).toBe(instance.proxy.number) + expect(instance.shortNumber()).toBe(0) + + number.set(1) + fixture.detectChanges() + + expect(instance.shortNumber).toBe(instance.proxy.number) + expect(instance.shortNumber()).toBe(1) + expect(fixture.nativeElement.textContent).toBe('1') + }) + }) +}) diff --git a/packages/angular-query/src/__tests__/test-utils.ts b/packages/angular-query/src/__tests__/test-utils.ts new file mode 100644 index 00000000000..cc7151fc8de --- /dev/null +++ b/packages/angular-query/src/__tests__/test-utils.ts @@ -0,0 +1,78 @@ +// cspell:ignore ZONEFUL zoneful +import { + isSignal, + provideZoneChangeDetection, + provideZonelessChangeDetection, + untracked, +} from '@angular/core' +import { TestBed } from '@angular/core/testing' +import { expect, vi } from 'vitest' +import { provideTanStackQuery } from '..' +import type { QueryClient } from '@tanstack/query-core' +import type { EnvironmentProviders, Provider, Signal } from '@angular/core' + +/** + * Use the same change-detection mode as the test runner. The default runner + * is zoneless; the zoneful runner sets ANGULAR_QUERY_ZONEFUL before loading + * tests and installs the real Zone.js testing patches. + */ +export function provideAngularQueryChangeDetection(): EnvironmentProviders { + return process.env.ANGULAR_QUERY_ZONEFUL === 'true' + ? provideZoneChangeDetection() + : provideZonelessChangeDetection() +} + +function evaluateSignals>( + obj: T, +): { [K in keyof T]: ReturnType } { + const result: Partial<{ [K in keyof T]: ReturnType }> = {} + + untracked(() => { + for (const key in obj) { + if ( + Object.prototype.hasOwnProperty.call(obj, key) && + isSignal(obj[key]) + ) { + const func = obj[key] + result[key] = func() + } + } + }) + + return result as { [K in keyof T]: ReturnType } +} + +export const expectSignals = >( + obj: T, + expected: Partial<{ + [K in keyof T]: T[K] extends Signal ? ReturnType : never + }>, +): void => { + expect(evaluateSignals(obj)).toMatchObject(expected) +} + +/** + * Reset Angular's TestBed and configure the standard TanStack Query providers for tests. + * Pass additional providers (including EnvironmentProviders) via the options argument. + */ +export function setupTanStackQueryTestBed( + queryClient: QueryClient, + options: { providers?: Array } = {}, +) { + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => queryClient), + ...(options.providers ?? []), + ], + }) +} + +/** + * Advances zero-delay timers and their promise continuations in fake-timer tests. + * Angular rendering may require a subsequent change-detection pass. + */ +export async function flushQueryUpdates() { + await vi.advanceTimersByTimeAsync(0) +} diff --git a/packages/angular-query/src/__tests__/upstream-issues.test.ts b/packages/angular-query/src/__tests__/upstream-issues.test.ts new file mode 100644 index 00000000000..39b33d520ea --- /dev/null +++ b/packages/angular-query/src/__tests__/upstream-issues.test.ts @@ -0,0 +1,289 @@ +import { + ApplicationRef, + ChangeDetectionStrategy, + Component, + VERSION, + effect, + input, + signal, +} from '@angular/core' +import { TestBed } from '@angular/core/testing' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { + QueryClient, + injectMutation, + injectQuery, + provideTanStackQuery, +} from '..' +import { provideAngularQueryChangeDetection } from './test-utils' + +// Reproductions transcribed from TanStack/query issues. Use real promises and +// Angular stability, without notification-scheduler overrides or timer flushes. +describe('upstream Angular issue reproductions', () => { + let client: QueryClient + + beforeEach(() => { + vi.useRealTimers() + if ( + process.env.ANGULAR_ISSUE_VERSION && + VERSION.full !== process.env.ANGULAR_ISSUE_VERSION + ) { + throw new Error(`Unexpected Angular runtime: ${VERSION.full}`) + } + client = new QueryClient({ + defaultOptions: { queries: { retry: false, gcTime: Infinity } }, + }) + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + provideTanStackQuery(() => client), + ], + }) + }) + + afterEach(() => { + TestBed.resetTestingModule() + client.clear() + }) + + it('#9910: a template signal read does not prevent whenStable from seeing success', async () => { + @Component({ template: '{{ query.isSuccess() }}' }) + class App { + query = injectQuery(() => ({ + queryKey: ['9910'], + queryFn: () => Promise.resolve([1, 2, 3, 4, 5]), + })) + } + const fixture = TestBed.createComponent(App) + fixture.detectChanges() + await fixture.whenStable() + fixture.detectChanges() + expect(fixture.componentInstance.query.isSuccess()).toBe(true) + expect(fixture.componentInstance.query.data()).toEqual([1, 2, 3, 4, 5]) + expect(fixture.nativeElement.textContent).toBe('true') + }) + + it('#10046: a class-field data alias is populated after whenStable', async () => { + @Component({ template: '{{ data() }}' }) + class App { + query = injectQuery(() => ({ + queryKey: ['10046'], + queryFn: () => Promise.resolve('loaded'), + })) + data = this.query.data + } + const fixture = TestBed.createComponent(App) + fixture.detectChanges() + await fixture.whenStable() + fixture.detectChanges() + expect(fixture.componentInstance.data()).toBe('loaded') + expect(fixture.nativeElement.textContent).toBe('loaded') + }) + + it.each(['TestBed', 'Testing Library'] as const)( + '#9981: an isSuccess effect updates component state using %s', + async (runner) => { + @Component({ + template: '{{ value }}', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class App { + value = 42 + query = injectQuery(() => ({ + queryKey: ['9981'], + queryFn: () => Promise.resolve([30, 40, 50]), + })) + constructor() { + effect(() => { + if (this.query.isSuccess()) this.value = 9999 + }) + } + } + const fixture = + runner === 'TestBed' + ? TestBed.createComponent(App) + : (await (await import('@testing-library/angular')).render(App)) + .fixture + fixture.detectChanges() + await fixture.whenStable() + fixture.detectChanges() + expect(fixture.componentInstance.value).toBe(9999) + }, + ) + + it('#7488: taking a data alias does not read an unset required input', async () => { + const optionsRead = vi.fn() + @Component({ template: '{{ data() }}' }) + class App { + name = input.required() + data = injectQuery(() => { + optionsRead() + return { + queryKey: ['7488', this.name()], + queryFn: () => Promise.resolve(this.name()), + } + }).data + } + const fixture = TestBed.createComponent(App) + expect(optionsRead).not.toHaveBeenCalled() + fixture.componentRef.setInput('name', 'ready') + fixture.detectChanges() + await fixture.whenStable() + expect(fixture.componentInstance.data()).toBe('ready') + expect(optionsRead).toHaveBeenCalledTimes(1) + }) + + it.each(['constructor', 'ngOnInit', 'ngAfterContentInit'] as const)( + '#9020: mutate immediately exposes pending from %s', + async (phase) => { + let finish!: (value: string) => void + const request = new Promise((resolve) => { + finish = resolve + }) + @Component({ template: '{{ mutation.status() }}' }) + class App { + immediate = '' + mutation = injectMutation(() => ({ mutationFn: () => request })) + constructor() { + if (phase === 'constructor') this.start() + } + ngOnInit() { + if (phase === 'ngOnInit') this.start() + } + ngAfterContentInit() { + if (phase === 'ngAfterContentInit') this.start() + } + start() { + this.mutation.mutate() + this.immediate = this.mutation.status() + } + } + const fixture = TestBed.createComponent(App) + fixture.detectChanges() + expect(fixture.componentInstance.immediate).toBe('pending') + expect(fixture.nativeElement.textContent).toBe('pending') + finish('done') + await fixture.whenStable() + expect(fixture.componentInstance.mutation.data()).toBe('done') + }, + ) + + it('#11176: whenStable waits for a just-triggered fire-and-forget mutation', async () => { + const app = TestBed.inject(ApplicationRef) + const mutation = TestBed.runInInjectionContext(() => + injectMutation(() => ({ + mutationFn: (value: string) => + new Promise((resolve) => { + setTimeout(() => resolve(value), 5) + }), + })), + ) + TestBed.tick() + mutation.mutate('mutated') + await app.whenStable() + expect(mutation.status()).toBe('success') + expect(mutation.data()).toBe('mutated') + }) + + it.each([false, true])( + '#11176: a newer mutation settling cannot release an older invocation (reset=%s)', + async (reset) => { + let finish!: () => void + const first = new Promise((resolve) => { + finish = resolve + }) + const mutation = TestBed.runInInjectionContext(() => + injectMutation(() => ({ + mutationFn: (request: Promise) => request, + })), + ) + TestBed.tick() + mutation.mutate(first) + if (reset) mutation.reset() + const second = mutation.mutateAsync(Promise.resolve()) + let stable = false + const settled = TestBed.inject(ApplicationRef) + .whenStable() + .then(() => { + stable = true + }) + await second + expect(stable).toBe(false) + finish() + await settled + expect(stable).toBe(true) + }, + ) + + it('#9735: saving an edit exposes optimistic data in the same turn and render', async () => { + const snapshots: Array = [] + @Component({ + template: '@if (!editing()) { {{ query.data() }} }', + changeDetection: ChangeDetectionStrategy.OnPush, + }) + class App { + editing = signal(true) + query = injectQuery(() => ({ + queryKey: ['9735'], + queryFn: () => Promise.resolve('old title'), + initialData: 'old title', + staleTime: Infinity, + })) + mutation = injectMutation(() => ({ + mutationFn: async (title: string) => title, + onMutate: (title: string) => { + client.setQueryData(['9735'], title) + snapshots.push(this.query.data()) + }, + })) + save() { + this.mutation.mutate('new title') + this.editing.set(false) + snapshots.push(this.query.data()) + } + } + const fixture = TestBed.createComponent(App) + fixture.detectChanges() + fixture.componentInstance.save() + expect(snapshots).toEqual(['new title', 'new title']) + expect(client.getQueryData(['9735'])).toBe('new title') + fixture.detectChanges() + expect(fixture.nativeElement.textContent).toBe('new title') + await fixture.whenStable() + }) + + it('#6567: changing to another cached key updates data immediately', () => { + client.setQueryData(['6567', 'a'], 'A') + client.setQueryData(['6567', 'b'], 'B') + const key = signal('a') + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['6567', key()], + enabled: false, + })), + ) + expect(query.data()).toBe('A') + TestBed.tick() + key.set('b') + expect(query.data()).toBe('B') + }) + + it('#6771: enabling a fresh cached query and immediately refetching settles', async () => { + client.setQueryData(['6771'], 'cached') + const enabled = signal(false) + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['6771'], + enabled: enabled(), + staleTime: Infinity, + queryFn: () => Promise.resolve('updated'), + })), + ) + TestBed.tick() + enabled.set(true) + await query.refetch() + await TestBed.inject(ApplicationRef).whenStable() + expect(query.data()).toBe('updated') + expect(query.isRefetching()).toBe(false) + }) +}) diff --git a/packages/angular-query/src/__tests__/with-hydration.test.ts b/packages/angular-query/src/__tests__/with-hydration.test.ts new file mode 100644 index 00000000000..bcdb30b91ea --- /dev/null +++ b/packages/angular-query/src/__tests__/with-hydration.test.ts @@ -0,0 +1,325 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { + Component, + EnvironmentInjector, + PLATFORM_ID, + TransferState, + createEnvironmentInjector, + effect, + inject, + makeStateKey, + provideEnvironmentInitializer, +} from '@angular/core' +import { TestBed } from '@angular/core/testing' +import { render } from '@testing-library/angular' +import { queryKey, sleep } from '@tanstack/query-test-utils' +import { + QueryClient, + dehydrate, + injectQuery, + noop, + provideTanStackQuery, + withHydrationKey, + withNoQueryHydration, +} from '..' +import { INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY } from '../hydration-state-key' +import { provideAngularQueryChangeDetection } from './test-utils' +import type { DehydratedState } from '@tanstack/query-core' + +beforeEach(() => { + vi.useFakeTimers() +}) + +afterEach(() => { + vi.restoreAllMocks() + vi.useRealTimers() +}) + +describe('TransferState hydration (client)', () => { + it('browser hydrates from default key', async () => { + const key = queryKey() + const sourceClient = new QueryClient() + sourceClient.setQueryData(key, 'from-server') + const dehydrated = dehydrate(sourceClient) + const appClient = new QueryClient() + + @Component({ + template: `
{{ state.data() ?? '' }}
`, + }) + class Page { + state = injectQuery(() => ({ + queryKey: key, + queryFn: () => sleep(10).then(() => 'from-client'), + })) + } + + const rendered = await render(Page, { + providers: [ + provideAngularQueryChangeDetection(), + provideEnvironmentInitializer(() => { + inject(TransferState).set( + INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY, + dehydrated, + ) + }), + provideTanStackQuery(() => appClient), + ], + }) + + rendered.fixture.detectChanges() + expect(rendered.getByText('from-server')).toBeInTheDocument() + expect( + rendered.fixture.debugElement.injector + .get(TransferState) + .get(INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY, null), + ).toBeNull() + }) + + it('browser hydrates from custom key', async () => { + const customKeyName = 'tanstack-test-custom-hydration' + const customKey = makeStateKey(customKeyName) + const key = queryKey() + const sourceClient = new QueryClient() + sourceClient.setQueryData(key, 'from-custom-key') + const dehydrated = dehydrate(sourceClient) + const appClient = new QueryClient() + + @Component({ + template: `
{{ state.data() ?? '' }}
`, + }) + class Page { + state = injectQuery(() => ({ + queryKey: key, + staleTime: Infinity, + queryFn: () => Promise.resolve('from-client'), + })) + } + + const rendered = await render(Page, { + providers: [ + provideAngularQueryChangeDetection(), + provideEnvironmentInitializer(() => { + inject(TransferState).set(customKey, dehydrated) + }), + provideTanStackQuery(() => appClient, withHydrationKey(customKeyName)), + ], + }) + + rendered.fixture.detectChanges() + expect(rendered.getByText('from-custom-key')).toBeTruthy() + expect( + rendered.fixture.debugElement.injector + .get(TransferState) + .get(customKey, null), + ).toBeNull() + }) + + it('browser does not re-fetch when hydrated state is fresh', async () => { + const key = queryKey() + const sourceClient = new QueryClient() + sourceClient.setQueryData(key, 'cached') + const dehydrated = dehydrate(sourceClient) + const appClient = new QueryClient() + let queryFnCalls = 0 + + @Component({ + template: `
{{ state.data() ?? '' }}
`, + }) + class Page { + state = injectQuery(() => ({ + queryKey: key, + staleTime: Infinity, + queryFn: () => { + queryFnCalls++ + return sleep(10).then(() => 'should-not-run') + }, + })) + + _ = effect(() => { + void this.state.data() + }) + } + + await render(Page, { + providers: [ + provideAngularQueryChangeDetection(), + provideEnvironmentInitializer(() => { + inject(TransferState).set( + INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY, + dehydrated, + ) + }), + provideTanStackQuery(() => appClient), + ], + }) + + await vi.advanceTimersByTimeAsync(100) + expect(queryFnCalls).toBe(0) + }) + + it('withNoQueryHydration disables browser hydration', async () => { + const key = queryKey() + const sourceClient = new QueryClient() + sourceClient.setQueryData(key, 'from-server') + const dehydrated = dehydrate(sourceClient) + const appClient = new QueryClient() + + @Component({ + template: `
{{ state.data() ?? '' }}
`, + }) + class Page { + state = injectQuery(() => ({ + queryKey: key, + queryFn: () => sleep(10).then(() => 'from-client'), + })) + } + + const rendered = await render(Page, { + providers: [ + provideAngularQueryChangeDetection(), + provideEnvironmentInitializer(() => { + inject(TransferState).set( + INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY, + dehydrated, + ) + }), + provideTanStackQuery(() => appClient, withNoQueryHydration()), + ], + }) + + rendered.fixture.detectChanges() + await vi.advanceTimersByTimeAsync(10) + rendered.fixture.detectChanges() + + expect(rendered.getByText('from-client')).toBeInTheDocument() + expect( + rendered.fixture.debugElement.injector + .get(TransferState) + .get(INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY, null), + ).toEqual(dehydrated) + }) +}) + +describe('TransferState dehydration (server)', () => { + function createQueryInjector( + queryClient: QueryClient, + platformId: 'server' | 'browser', + ...features: Array[1]> + ) { + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + { provide: PLATFORM_ID, useValue: platformId }, + ], + }) + + return createEnvironmentInjector( + [provideTanStackQuery(() => queryClient, ...features)], + TestBed.inject(EnvironmentInjector), + ) + } + + it('server serializes dehydrated queries on TransferState.toJson', async () => { + const key = queryKey() + const queryClient = new QueryClient() + const injector = createQueryInjector(queryClient, 'server') + + void queryClient.query({ + queryKey: key, + queryFn: () => Promise.resolve('ssr-data'), + }).catch(noop) + await vi.advanceTimersByTimeAsync(0) + + injector.get(TransferState).toJson() + + const stored = injector + .get(TransferState) + .get(INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY, null) + expect(stored).not.toBeNull() + if (!stored) throw new Error('expected dehydrated state') + expect(stored.queries.length).toBe(1) + expect(stored.queries[0]?.queryKey).toEqual(key) + }) + + it('browser platform does not write server dehydration state', async () => { + const key = queryKey() + const queryClient = new QueryClient() + const injector = createQueryInjector(queryClient, 'browser') + + void queryClient.query({ + queryKey: key, + queryFn: () => Promise.resolve('data'), + }).catch(noop) + await vi.advanceTimersByTimeAsync(0) + + injector.get(TransferState).toJson() + + expect( + injector + .get(TransferState) + .get(INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY, null), + ).toBeNull() + }) + + it('withNoQueryHydration disables server dehydration', async () => { + const key = queryKey() + const queryClient = new QueryClient() + const injector = createQueryInjector( + queryClient, + 'server', + withNoQueryHydration(), + ) + + void queryClient.query({ + queryKey: key, + queryFn: () => Promise.resolve('data'), + }).catch(noop) + await vi.advanceTimersByTimeAsync(0) + + injector.get(TransferState).toJson() + + expect( + injector + .get(TransferState) + .get(INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY, null), + ).toBeNull() + }) + + it('multiple query clients can use distinct hydration keys', async () => { + const keyA = queryKey() + const keyB = queryKey() + const clientA = new QueryClient() + const clientB = new QueryClient() + + TestBed.configureTestingModule({ + providers: [ + provideAngularQueryChangeDetection(), + { provide: PLATFORM_ID, useValue: 'server' }, + ], + }) + + createEnvironmentInjector( + [provideTanStackQuery(() => clientA, withHydrationKey('client-a'))], + TestBed.inject(EnvironmentInjector), + ) + createEnvironmentInjector( + [provideTanStackQuery(() => clientB, withHydrationKey('client-b'))], + TestBed.inject(EnvironmentInjector), + ) + + clientA.setQueryData(keyA, 'a') + clientB.setQueryData(keyB, 'b') + + const transferState = TestBed.inject(TransferState) + transferState.toJson() + + expect( + transferState.get(makeStateKey('client-a'), null) + ?.queries[0]?.queryKey, + ).toEqual(keyA) + expect( + transferState.get(makeStateKey('client-b'), null) + ?.queries[0]?.queryKey, + ).toEqual(keyB) + }) +}) diff --git a/packages/angular-query/src/__tests__/zoneful-integration.test.ts b/packages/angular-query/src/__tests__/zoneful-integration.test.ts new file mode 100644 index 00000000000..cf5cc85c8c7 --- /dev/null +++ b/packages/angular-query/src/__tests__/zoneful-integration.test.ts @@ -0,0 +1,191 @@ +// cspell:ignore zoneful +import { + ApplicationRef, + Component, + NgZone, + provideZoneChangeDetection, + signal, +} from '@angular/core' +import { TestBed } from '@angular/core/testing' +import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import { provideIsRestoring } from '../internal' +import { + QueryClient, + injectMutation, + injectQueries, + injectQuery, + provideTanStackQuery, +} from '..' + +/** + * These tests deliberately provide Angular's zone-based scheduler directly. + * They are run by vitest.zoneful.config.ts, whose setup also loads the Zone.js + * testing patches. Keeping this small integration set separate avoids making + * every signal assertion in the zoneless suite depend on Zone.js scheduling. + */ +describe('Zone.js notification integration', () => { + let queryClient: QueryClient + + beforeEach(() => { + queryClient = new QueryClient() + TestBed.configureTestingModule({ + providers: [ + provideZoneChangeDetection(), + provideTanStackQuery(() => queryClient), + ], + }) + }) + + afterEach(() => { + TestBed.resetTestingModule() + }) + + it('keeps an injectQuery signal current after its subscription commits', () => { + const key = ['zoneful-query'] + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: key, + enabled: false, + })), + ) + + expect(query.data()).toBeUndefined() + TestBed.tick() + queryClient.setQueryData(key, 'updated') + + expect(query.data()).toBe('updated') + }) + + it('keeps injectQueries current after its subscription commits', () => { + const key = ['zoneful-queries'] + const queries = TestBed.runInInjectionContext(() => + injectQueries(() => ({ + queries: [{ queryKey: key, enabled: false }], + })), + ) + + expect(queries()[0].data()).toBeUndefined() + TestBed.tick() + queryClient.setQueryData(key, 'updated') + + expect(queries()[0].data()).toBe('updated') + }) + + it('makes committed query notifications visible inside mutation onMutate', async () => { + const key = ['zoneful-optimistic'] + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: key, + enabled: false, + })), + ) + const seenInOnMutate: Array = [] + const mutation = TestBed.runInInjectionContext(() => + injectMutation(() => ({ + mutationKey: ['zoneful-mutation'], + mutationFn: async () => 'server', + onMutate: () => { + queryClient.setQueryData(key, 'optimistic') + seenInOnMutate.push(query.data() as string | undefined) + }, + })), + ) + + query.data() + TestBed.tick() + await mutation.mutateAsync() + + expect(seenInOnMutate).toEqual(['optimistic']) + }) + + it('uses the latest options when restoration ends in the same Zone.js turn', async () => { + const isRestoring = signal(true) + const key = signal('old') + const queriedKeys: Array = [] + + TestBed.resetTestingModule() + TestBed.configureTestingModule({ + providers: [ + provideZoneChangeDetection(), + provideTanStackQuery(() => queryClient), + provideIsRestoring(() => isRestoring.asReadonly()), + ], + }) + + const query = TestBed.runInInjectionContext(() => + injectQuery(() => ({ + queryKey: ['zoneful-restoration', key()], + queryFn: ({ queryKey }) => { + const currentKey = queryKey[1] as string + queriedKeys.push(currentKey) + return Promise.resolve(currentKey) + }, + })), + ) + + expect(query.status()).toBe('pending') + key.set('new') + isRestoring.set(false) + TestBed.tick() + await TestBed.inject(ApplicationRef).whenStable() + + expect(queriedKeys).toEqual(['new']) + expect(query.data()).toBe('new') + expect( + queryClient + .getQueryCache() + .find({ queryKey: ['zoneful-restoration', 'new'] }) + ?.getObserversCount(), + ).toBe(1) + }) + + it('completes dependent queries before application stability without manual effect flushing', async () => { + @Component({ template: '{{ second.data() }}' }) + class Page { + first = injectQuery(() => ({ + queryKey: ['zoneful-dependency-first'], + queryFn: async () => 'ready', + })) + second = injectQuery(() => ({ + queryKey: ['zoneful-dependency-second'], + enabled: this.first.isSuccess(), + queryFn: async () => 'dependent data', + })) + } + + const fixture = TestBed.createComponent(Page) + fixture.autoDetectChanges() + await TestBed.inject(ApplicationRef).whenStable() + expect(fixture.componentInstance.second.data()).toBe('dependent data') + }) + it('renders outside-zone query, multi-query and mutation notifications automatically', async () => { + @Component({ + template: + '{{ query.data() }} / {{ queries()[0].data() }} / {{ mutation.status() }}', + }) + class Page { + query = injectQuery(() => ({ + queryKey: ['outside-single'], + enabled: false, + })) + queries = injectQueries(() => ({ + queries: [{ queryKey: ['outside-multiple'], enabled: false }], + })) + mutation = injectMutation(() => ({ mutationFn: async () => 'done' })) + } + const fixture = TestBed.createComponent(Page) + fixture.autoDetectChanges() + await fixture.whenStable() + const zone = TestBed.inject(NgZone) + const promise = zone.runOutsideAngular(() => { + queryClient.setQueryData(['outside-single'], 'single') + queryClient.setQueryData(['outside-multiple'], 'multiple') + return fixture.componentInstance.mutation.mutateAsync() + }) + await promise + await fixture.whenStable() + expect(fixture.nativeElement.textContent).toBe( + 'single / multiple / success', + ) + }) +}) diff --git a/packages/angular-query/src/hydration-state-key.ts b/packages/angular-query/src/hydration-state-key.ts new file mode 100644 index 00000000000..0dd2c3ee2c9 --- /dev/null +++ b/packages/angular-query/src/hydration-state-key.ts @@ -0,0 +1,15 @@ +import { InjectionToken, makeStateKey } from '@angular/core' +import type {StateKey} from '@angular/core'; +import type { DehydratedState } from '@tanstack/query-core' + +export const INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY = + makeStateKey('tanstack-query-hydration-state') + +export const INTERNAL_TANSTACK_QUERY_HYDRATION_TRANSFER_KEY = + new InjectionToken>( + 'tanstack-query-hydration-transfer-key', + { + providedIn: 'root', + factory: () => INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY, + }, + ) diff --git a/packages/angular-query-experimental/src/index.ts b/packages/angular-query/src/index.ts similarity index 56% rename from packages/angular-query-experimental/src/index.ts rename to packages/angular-query/src/index.ts index fc033224e51..ff9e4d81bd6 100644 --- a/packages/angular-query-experimental/src/index.ts +++ b/packages/angular-query/src/index.ts @@ -4,6 +4,8 @@ export * from '@tanstack/query-core' export * from './types' +export type { QueryResource } from './query-resource' +export { toResource } from './query-resource' export type { DefinedInitialDataOptions, @@ -22,39 +24,31 @@ export type { } from './infinite-query-options' export { infiniteQueryOptions } from './infinite-query-options' -export type { InjectInfiniteQueryOptions } from './inject-infinite-query' export { injectInfiniteQuery } from './inject-infinite-query' -export type { InjectIsFetchingOptions } from './inject-is-fetching' export { injectIsFetching } from './inject-is-fetching' -export type { InjectIsMutatingOptions } from './inject-is-mutating' export { injectIsMutating } from './inject-is-mutating' -export { injectIsRestoring, provideIsRestoring } from './inject-is-restoring' +export { injectIsRestoring } from './inject-is-restoring' -export type { InjectMutationOptions } from './inject-mutation' export { injectMutation } from './inject-mutation' -export type { InjectMutationStateOptions } from './inject-mutation-state' +export type { MutationStateOptions } from './inject-mutation-state' export { injectMutationState } from './inject-mutation-state' -export type { QueriesOptions, QueriesResults } from './inject-queries' +export type { + InjectQueriesOptions, + QueriesOptions, + QueriesResults, +} from './inject-queries.types' +export { injectQueries } from './inject-queries' -export type { InjectQueryOptions } from './inject-query' export { injectQuery } from './inject-query' -export { injectQueryClient } from './inject-query-client' - -export type { - DevtoolsFeature, - PersistQueryClientFeature, - QueryFeature, - QueryFeatures, -} from './providers' +export type { QueryFeature } from './providers' export { - provideAngularQuery, - provideQueryClient, provideTanStackQuery, - queryFeature, + withHydrationKey, + withNoQueryHydration, } from './providers' diff --git a/packages/angular-query-experimental/src/infinite-query-options.ts b/packages/angular-query/src/infinite-query-options.ts similarity index 99% rename from packages/angular-query-experimental/src/infinite-query-options.ts rename to packages/angular-query/src/infinite-query-options.ts index d114e2dac63..f22099373f5 100644 --- a/packages/angular-query-experimental/src/infinite-query-options.ts +++ b/packages/angular-query/src/infinite-query-options.ts @@ -129,7 +129,6 @@ export type DefinedInitialDataInfiniteOptions< initialData: | NonUndefinedGuard> | (() => NonUndefinedGuard>) - | undefined } /** @@ -149,7 +148,7 @@ export type DefinedInitialDataInfiniteOptions< * * @example * ```angular-ts - * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' + * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query' * * export const projectsOptions = infiniteQueryOptions({ * queryKey: ['projects'], @@ -214,7 +213,7 @@ export function infiniteQueryOptions< * @example * A parameterized factory, so the same options object can be reused per `postId`: * ```angular-ts - * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' + * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query' * * export const commentsOptions = (postId: string) => * infiniteQueryOptions({ @@ -288,7 +287,7 @@ export function infiniteQueryOptions< * @example * A parameterized factory, so the same options object can be reused per `postId`: * ```angular-ts - * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' + * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query' * * export const commentsOptions = (postId: string) => * infiniteQueryOptions({ diff --git a/packages/angular-query/src/inject-base-query.ts b/packages/angular-query/src/inject-base-query.ts new file mode 100644 index 00000000000..d36f9f30c24 --- /dev/null +++ b/packages/angular-query/src/inject-base-query.ts @@ -0,0 +1,107 @@ +import { computed, effect, inject, untracked } from '@angular/core' +import { QueryClient } from '@tanstack/query-core' +import { injectQueryZone } from './utils/inject-query-zone' +import { injectIsRestoring } from './inject-is-restoring' +import { injectPendingTasksLifecycle } from './utils/inject-pending-tasks-lifecycle' +import { injectExternalStore } from './utils/inject-external-store' +import type { + QueryKey, + QueryObserver, + QueryObserverOptions, + QueryObserverResult, +} from '@tanstack/query-core' + +/** + * Base implementation for `injectQuery` and `injectInfiniteQuery`. + */ +export function injectBaseQuery< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey extends QueryKey, +>( + optionsFn: () => QueryObserverOptions< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey + >, + Observer: typeof QueryObserver, +) { + const outsideZone = injectQueryZone() + const queryClient = inject(QueryClient) + const isRestoring = injectIsRestoring() + const lifecycle = injectPendingTasksLifecycle() + + const shouldBlockPendingTasks = ( + observer: QueryObserver, + result: QueryObserverResult, + ) => { + return ( + observer.getCurrentQuery().state.fetchStatus !== 'idle' || + (result.fetchStatus !== 'idle' && result.isEnabled) + ) + } + + const defaultedOptionsSignal = computed(() => { + const defaultedOptions = queryClient.defaultQueryOptions(optionsFn()) + defaultedOptions._optimisticResults = isRestoring() + ? 'isRestoring' + : 'optimistic' + defaultedOptions.notifyOnChangeProps = 'all' + return defaultedOptions + }) + + const observerSignal = computed( + () => new Observer(queryClient, untracked(defaultedOptionsSignal)), + ) + + effect(() => { + const options = defaultedOptionsSignal() + outsideZone(() => untracked(() => observerSignal().setOptions(options))) + }) + + const resultSignal = injectExternalStore(() => { + const observer = observerSignal() + const restoring = isRestoring() + return { + getSnapshot: () => observer.getOptimisticResult(defaultedOptionsSignal()), + subscribe: restoring + ? undefined + : (onStoreChange) => { + const unsubscribe = observer.subscribe(() => { + if (lifecycle.destroyed) return + onStoreChange() + }) + return () => { + lifecycle.setPending(false) + unsubscribe() + } + }, + } + }) + + effect((onCleanup) => { + const result = resultSignal() + if (isRestoring()) { + lifecycle.setPending(false) + return + } + + lifecycle.setPending(shouldBlockPendingTasks(observerSignal(), result)) + onCleanup(() => lifecycle.setPending(false)) + }) + + // Imperative methods use current options before starting work, even when + // invoked before the subscription effect runs. + const getObserver = () => + untracked(() => { + const observer = observerSignal() + observer.setOptions(defaultedOptionsSignal()) + return observer + }) + + return [resultSignal, getObserver] as const +} diff --git a/packages/angular-query/src/inject-infinite-query.ts b/packages/angular-query/src/inject-infinite-query.ts new file mode 100644 index 00000000000..f557fc1875c --- /dev/null +++ b/packages/angular-query/src/inject-infinite-query.ts @@ -0,0 +1,200 @@ +import { InfiniteQueryObserver } from '@tanstack/query-core' +import { assertInInjectionContext, untracked } from '@angular/core' +import { injectQueryZone } from './utils/inject-query-zone' +import { injectBaseQuery } from './inject-base-query' +import { signalProxy } from './utils/signal-proxy' +import { infiniteQueryResultFields } from './utils/result-fields' +import type { + DefaultError, + FetchNextPageOptions, + FetchPreviousPageOptions, + InfiniteData, + InfiniteQueryObserverResult, + QueryKey, + QueryObserver, + RefetchOptions, +} from '@tanstack/query-core' +import type { Signal } from '@angular/core' +import type { + CreateInfiniteQueryOptions, + CreateInfiniteQueryResult, + DefinedCreateInfiniteQueryResult, +} from './types' +import type { + DefinedInitialDataInfiniteOptions, + UndefinedInitialDataInfiniteOptions, +} from './infinite-query-options' + +/** + * This overload is selected when `initialData` is set, so the resulting `data` signal is never `undefined` + * (unless a `select` changes `TData` to include `undefined`). + * + * @see https://tanstack.com/query/latest/docs/framework/angular/guides/infinite-queries + * @see {@link infiniteQueryOptions} to share these options between `injectInfiniteQuery` and + * `queryClient.infiniteQuery`. + * @param optionsFn - A function returning infinite-query options with `initialData` set. Similar to + * `computed` from Angular, this function runs in the reactive context. + * @returns The infinite query result, typed so that `data` is never `undefined`. + */ +export function injectInfiniteQuery< + TQueryFnData, + TError = DefaultError, + TData = InfiniteData, + TQueryKey extends QueryKey = QueryKey, + TPageParam = unknown, +>( + optionsFn: () => DefinedInitialDataInfiniteOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam + >, +): DefinedCreateInfiniteQueryResult + +/** + * Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key. + * Infinite queries can additively "load more" data onto an existing set of data or support infinite scroll. + * + * @see https://tanstack.com/query/latest/docs/framework/angular/guides/infinite-queries + * @see {@link infiniteQueryOptions} to share these options between `injectInfiniteQuery` and + * `queryClient.infiniteQuery`. + * @param optionsFn - A function that returns infinite query options. Similar to `computed` from Angular, + * this function runs in the reactive context, so signals read inside it drive the query. + * @returns The infinite query result. + * + * @example + * ```angular-ts + * @Component({ + * selector: 'projects', + * template: ` + * @if (query.isPending()) { + * Loading... + * } @else if (query.isError()) { + * Error: {{ query.error()?.message }} + * } @else { + * @for (page of query.data().pages; track $index) { + * @for (project of page; track project.id) { + *

{{ project.name }}

+ * } + * } + * + * } + * `, + * }) + * export class Projects { + * readonly query = injectInfiniteQuery(() => ({ + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextCursor, + * })) + * } + * ``` + */ +export function injectInfiniteQuery< + TQueryFnData, + TError = DefaultError, + TData = InfiniteData, + TQueryKey extends QueryKey = QueryKey, + TPageParam = unknown, +>( + optionsFn: () => UndefinedInitialDataInfiniteOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam + >, +): CreateInfiniteQueryResult + +/** + * This overload accepts the general {@link CreateInfiniteQueryOptions} shape rather than the + * `initialData`-aware overloads above, so whether `data` is defined can't be inferred from the call + * site — useful when wrapping `injectInfiniteQuery` in your own helper. + * + * @see https://tanstack.com/query/latest/docs/framework/angular/guides/infinite-queries + * @param optionsFn - A function that returns infinite query options. Similar to `computed` from Angular, + * this function runs in the reactive context, so signals read inside it drive the query. + * @returns The infinite query result. + */ +export function injectInfiniteQuery< + TQueryFnData, + TError = DefaultError, + TData = InfiniteData, + TQueryKey extends QueryKey = QueryKey, + TPageParam = unknown, +>( + optionsFn: () => CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam + >, +): CreateInfiniteQueryResult + +export function injectInfiniteQuery< + TQueryFnData, + TError = DefaultError, + TData = InfiniteData, + TQueryKey extends QueryKey = QueryKey, + TPageParam = unknown, +>( + optionsFn: () => + | DefinedInitialDataInfiniteOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam + > + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam + >, +): + | DefinedCreateInfiniteQueryResult + | CreateInfiniteQueryResult { + if (typeof ngDevMode === 'undefined' || ngDevMode) { + assertInInjectionContext(injectInfiniteQuery) + } + const outsideZone = injectQueryZone() + const [resultSignal, getObserver] = injectBaseQuery( + optionsFn, + InfiniteQueryObserver as typeof QueryObserver, + ) + const getInfiniteObserver = () => + getObserver() as InfiniteQueryObserver< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam + > + return Object.assign( + signalProxy( + resultSignal as Signal>, + infiniteQueryResultFields, + ), + { + refetch: (options?: RefetchOptions) => + outsideZone(() => + untracked(() => getInfiniteObserver().refetch(options)), + ), + fetchNextPage: (options?: FetchNextPageOptions) => + outsideZone(() => + untracked(() => getInfiniteObserver().fetchNextPage(options)), + ), + fetchPreviousPage: (options?: FetchPreviousPageOptions) => + outsideZone(() => + untracked(() => getInfiniteObserver().fetchPreviousPage(options)), + ), + }, + ) as unknown as + | DefinedCreateInfiniteQueryResult + | CreateInfiniteQueryResult +} diff --git a/packages/angular-query/src/inject-is-fetching.ts b/packages/angular-query/src/inject-is-fetching.ts new file mode 100644 index 00000000000..4d104766ce4 --- /dev/null +++ b/packages/angular-query/src/inject-is-fetching.ts @@ -0,0 +1,28 @@ +import { assertInInjectionContext, inject } from '@angular/core' +import { QueryClient } from '@tanstack/query-core' +import { injectExternalStore } from './utils/inject-external-store' +import type { QueryFilters } from '@tanstack/query-core' +import type { Signal } from '@angular/core' + +/** + * Injects a signal that tracks the number of queries that your application is loading or fetching in the + * background (useful for app-wide loading indicators). + * + * Can be used for app-wide loading indicators + * @param filters - A reactive factory for the filters. + * @returns signal with number of loading or fetching queries. + */ +export function injectIsFetching( + filters: () => QueryFilters = () => ({}), +): Signal { + if (typeof ngDevMode === 'undefined' || ngDevMode) { + assertInInjectionContext(injectIsFetching) + } + const queryClient = inject(QueryClient) + const cache = queryClient.getQueryCache() + + return injectExternalStore(() => ({ + getSnapshot: () => queryClient.isFetching(filters()), + subscribe: (onStoreChange) => cache.subscribe(onStoreChange), + })) +} diff --git a/packages/angular-query/src/inject-is-mutating.ts b/packages/angular-query/src/inject-is-mutating.ts new file mode 100644 index 00000000000..84fd6f4051d --- /dev/null +++ b/packages/angular-query/src/inject-is-mutating.ts @@ -0,0 +1,28 @@ +import { assertInInjectionContext, inject } from '@angular/core' +import { QueryClient } from '@tanstack/query-core' +import { injectExternalStore } from './utils/inject-external-store' +import type { MutationFilters } from '@tanstack/query-core' +import type { Signal } from '@angular/core' + +/** + * Injects a signal that tracks the number of mutations that your application currently has `pending` + * (useful for app-wide loading indicators). + * + * Can be used for app-wide loading indicators + * @param filters - A reactive factory for the filters. + * @returns A read-only signal with the number of fetching mutations. + */ +export function injectIsMutating( + filters: () => MutationFilters = () => ({}), +): Signal { + if (typeof ngDevMode === 'undefined' || ngDevMode) { + assertInInjectionContext(injectIsMutating) + } + const queryClient = inject(QueryClient) + const cache = queryClient.getMutationCache() + + return injectExternalStore(() => ({ + getSnapshot: () => queryClient.isMutating(filters()), + subscribe: (onStoreChange) => cache.subscribe(onStoreChange), + })) +} diff --git a/packages/angular-query/src/inject-is-restoring.ts b/packages/angular-query/src/inject-is-restoring.ts new file mode 100644 index 00000000000..7a155a51808 --- /dev/null +++ b/packages/angular-query/src/inject-is-restoring.ts @@ -0,0 +1,40 @@ +import { + InjectionToken, + assertInInjectionContext, + inject, + signal, +} from '@angular/core' +import type { Provider, Signal } from '@angular/core' + +/** + * Internal token used to track isRestoring state, accessible in public API through `injectIsRestoring` and set via `provideIsRestoring` + */ +const IS_RESTORING = new InjectionToken('', { + factory: () => signal(false).asReadonly(), +}) + +/** + * Injects a readonly signal that is true while the persistence integration restores + * cached query data. Returns false when no restoration is in progress. + * @returns The current restoration state. + */ +export function injectIsRestoring() { + if (typeof ngDevMode === 'undefined' || ngDevMode) { + assertInInjectionContext(injectIsRestoring) + } + return inject(IS_RESTORING) +} + +/** + * Supplies injector-scoped restoration state to the Angular Query integrations. + * The factory runs once in Angular's injection context. + * @internal + */ +export function provideIsRestoring( + isRestoringFactory: () => Signal, +): Provider { + return { + provide: IS_RESTORING, + useFactory: isRestoringFactory, + } +} diff --git a/packages/angular-query/src/inject-mutation-state.ts b/packages/angular-query/src/inject-mutation-state.ts new file mode 100644 index 00000000000..cf7d5aa4bd3 --- /dev/null +++ b/packages/angular-query/src/inject-mutation-state.ts @@ -0,0 +1,79 @@ +import { assertInInjectionContext, inject } from '@angular/core' +import { QueryClient } from '@tanstack/query-core' +import { injectExternalStore } from './utils/inject-external-store' +import type { Signal } from '@angular/core' +import type { + Mutation, + MutationCache, + MutationFilters, + MutationState, +} from '@tanstack/query-core' + +type MutationTypeFromResult = [TResult] extends [ + MutationState< + infer TData, + infer TError, + infer TVariables, + infer TOnMutateResult + >, +] + ? Mutation + : Mutation + +export type MutationStateOptions< + TResult = MutationState, + TMutation extends Mutation = + MutationTypeFromResult, +> = { + filters?: MutationFilters + select?: (mutation: TMutation) => TResult +} + +function getResult< + TResult = MutationState, + TMutation extends Mutation = + MutationTypeFromResult, +>( + mutationCache: MutationCache, + options: MutationStateOptions, +): Array { + return mutationCache + .findAll(options.filters) + .map( + (mutation): TResult => + (options.select + ? options.select(mutation as TMutation) + : mutation.state) as TResult, + ) +} + +/** + * Injects a signal that tracks the state of all mutations. + * @param options - A function that returns mutation state options. + * @returns The signal that tracks the state of all mutations. + */ +export function injectMutationState< + TResult = MutationState, + TMutation extends Mutation = + MutationTypeFromResult, +>( + options: () => MutationStateOptions = () => ({}), +): Signal> { + if (typeof ngDevMode === 'undefined' || ngDevMode) { + assertInInjectionContext(injectMutationState) + } + const queryClient = inject(QueryClient) + const mutationCache = queryClient.getMutationCache() + + return injectExternalStore( + () => ({ + getSnapshot: () => getResult(mutationCache, options()), + subscribe: (onStoreChange) => mutationCache.subscribe(onStoreChange), + }), + { + equal: (previous, next) => + previous.length === next.length && + previous.every((value, index) => Object.is(value, next[index])), + }, + ) +} diff --git a/packages/angular-query/src/inject-mutation.ts b/packages/angular-query/src/inject-mutation.ts new file mode 100644 index 00000000000..b319c09b11b --- /dev/null +++ b/packages/angular-query/src/inject-mutation.ts @@ -0,0 +1,153 @@ +import { + assertInInjectionContext, + computed, + effect, + inject, + untracked, +} from '@angular/core' +import { MutationObserver, QueryClient, noop } from '@tanstack/query-core' +import { injectQueryZone } from './utils/inject-query-zone' +import { signalProxy } from './utils/signal-proxy' +import { mutationResultFields } from './utils/result-fields' +import { injectPendingTasksLifecycle } from './utils/inject-pending-tasks-lifecycle' +import { injectExternalStore } from './utils/inject-external-store' +import type { DefaultError } from '@tanstack/query-core' +import type { + CreateMutateAsyncFunction, + CreateMutateFunction, + CreateMutationOptions, + CreateMutationResult, +} from './types' + +/** + * Injects a mutation: an imperative function that can be invoked which typically performs server side effects. + * Unlike queries, mutations are not run automatically. + * + * @see https://tanstack.com/query/latest/docs/framework/angular/guides/mutations + * @see {@link mutationOptions} to share these options between `injectMutation` and `injectMutationState`. + * @param optionsFn - A function that returns mutation options. Similar to `computed` from Angular, this + * function runs in the reactive context, so signals read inside it drive the mutation. + * @returns The mutation result, including `mutate` and `mutateAsync`. + * + * @example + * ```angular-ts + * @Component({ + * template: ` + * @if (mutation.isPending()) { + * Saving... + * } @else if (mutation.isError()) { + * Error: {{ mutation.error()?.message }} + * } + * + * `, + * }) + * export class CreatePost { + * readonly mutation = injectMutation(() => ({ + * mutationFn: createPost, + * })) + * } + * ``` + */ +export function injectMutation< + TData = unknown, + TError = DefaultError, + TVariables = void, + TOnMutateResult = unknown, +>( + optionsFn: () => CreateMutationOptions< + TData, + TError, + TVariables, + TOnMutateResult + >, +): CreateMutationResult { + if (typeof ngDevMode === 'undefined' || ngDevMode) { + assertInInjectionContext(injectMutation) + } + const outsideZone = injectQueryZone() + const queryClient = inject(QueryClient) + const lifecycle = injectPendingTasksLifecycle() + + const optionsSignal = computed(optionsFn) + + const observerSignal = computed( + () => new MutationObserver(queryClient, untracked(optionsSignal)), + ) + + // Configure the observer outside the result computation. Mutation-cache + // listeners can synchronously read the public result while setOptions emits. + effect(() => { + const options = optionsSignal() + outsideZone(() => untracked(() => observerSignal().setOptions(options))) + }) + + const mutationStateSignal = injectExternalStore(() => { + const observer = observerSignal() + return { + getSnapshot: () => observer.getCurrentResult(), + subscribe: (onStoreChange) => observer.subscribe(onStoreChange), + } + }) + + const mutate: CreateMutateFunction< + TData, + TError, + TVariables, + TOnMutateResult + > = (...args) => { + mutateAsync(...args).catch(noop) + } + + let pendingInvocations = 0 + + const mutateAsync: CreateMutateAsyncFunction< + TData, + TError, + TVariables, + TOnMutateResult + > = (...args) => { + return outsideZone(() => + untracked(() => { + const observer = observerSignal() + observer.setOptions(optionsSignal()) + pendingInvocations++ + lifecycle.setPending(true) + // Track invocations, not the observer's latest result: reset or a later + // mutation completing must not release work which is still running. + const settled = () => { + pendingInvocations-- + lifecycle.setPending(pendingInvocations > 0) + } + try { + return observer + .mutate(args[0] as TVariables, args[1]) + .finally(settled) + } catch (error) { + settled() + throw error + } + }), + ) + } + + const reset = () => { + outsideZone(() => + untracked(() => { + const observer = observerSignal() + observer.setOptions(optionsSignal()) + observer.reset() + }), + ) + } + + return Object.assign(signalProxy(mutationStateSignal, mutationResultFields), { + mutate, + mutateAsync, + reset, + }) as unknown as CreateMutationResult< + TData, + TError, + TVariables, + TOnMutateResult + > +} diff --git a/packages/angular-query/src/inject-queries.ts b/packages/angular-query/src/inject-queries.ts new file mode 100644 index 00000000000..8d243171e70 --- /dev/null +++ b/packages/angular-query/src/inject-queries.ts @@ -0,0 +1,201 @@ +import { QueriesObserver, QueryClient } from '@tanstack/query-core' +import { + assertInInjectionContext, + computed, + effect, + inject, + untracked, +} from '@angular/core' +import { injectQueryZone } from './utils/inject-query-zone' +import { signalProxy } from './utils/signal-proxy' +import { queryResultFields } from './utils/result-fields' +import { injectIsRestoring } from './inject-is-restoring' +import { injectPendingTasksLifecycle } from './utils/inject-pending-tasks-lifecycle' +import { injectExternalStore } from './utils/inject-external-store' +import type { + InjectQueriesOptions, + QueriesResults, +} from './inject-queries.types' +import type { + QueryObserverOptions, + QueryObserverResult, +} from '@tanstack/query-core' +import type { Signal } from '@angular/core' + +/** + * Injects multiple queries that run in parallel and react to Angular signals. + * + * @see https://tanstack.com/query/latest/docs/framework/angular/guides/parallel-queries + * @param optionsFn - A function that returns the queries' options. Similar to `computed` from Angular, + * this function runs in the reactive context, so signals read inside it drive the queries. + * @returns A signal containing the query results in the same order as the input queries. + * + * @example + * ```angular-ts + * @Component({ + * selector: 'users', + * template: ` + * @for (query of userQueries(); track $index) { + * @if (query.isSuccess()) { + *

{{ query.data().name }}

+ * } + * } + * `, + * }) + * export class UsersComponent { + * readonly users = input.required>() + * + * readonly userQueries = injectQueries(() => ({ + * queries: this.users().map((user) => ({ + * queryKey: ['user', user.id], + * queryFn: () => fetchUserById(user.id), + * })), + * })) + * } + * ``` + */ +export function injectQueries< + T extends Array, + TCombinedResult = QueriesResults, +>( + optionsFn: () => InjectQueriesOptions, +): Signal { + if (typeof ngDevMode === 'undefined' || ngDevMode) { + assertInInjectionContext(injectQueries) + } + const outsideZone = injectQueryZone() + const queryClient = inject(QueryClient) + const isRestoring = injectIsRestoring() + const lifecycle = injectPendingTasksLifecycle() + + const optionsSignal = computed(optionsFn) + + const defaultedQueries = computed(() => { + return optionsSignal().queries.map((opts) => { + const defaultedOptions = queryClient.defaultQueryOptions( + opts as QueryObserverOptions, + ) + defaultedOptions._optimisticResults = isRestoring() + ? 'isRestoring' + : 'optimistic' + defaultedOptions.notifyOnChangeProps = 'all' + + return defaultedOptions as QueryObserverOptions + }) + }) + + const shouldBlockPendingTasks = ( + observer: QueriesObserver, + results: Array, + ) => { + const queries = observer.getQueries() + + return results.some((result, index) => { + return ( + queries[index]?.state.fetchStatus !== 'idle' || + (result.fetchStatus !== 'idle' && result.isEnabled) + ) + }) + } + + const observerSignal = computed( + () => + new QueriesObserver( + queryClient, + untracked(defaultedQueries), + ), + ) + + effect(() => { + const queries = defaultedQueries() + outsideZone(() => untracked(() => observerSignal().setQueries(queries))) + }) + + // Methods address the current array slot, including methods handed to combine. + const refetches: Array = [] + const getRefetch = (index: number): QueryObserverResult['refetch'] => + (refetches[index] ??= (options) => + outsideZone(() => + untracked(() => { + const observer = observerSignal() + observer.setQueries(defaultedQueries()) + const queryObserver = observer.getObservers()[index] + if (!queryObserver) { + return Promise.reject( + new Error(`Cannot refetch removed query at index ${index}`), + ) + } + return queryObserver.refetch(options) + }), + )) + + const resultSignal = injectExternalStore(() => { + const observer = observerSignal() + const restoring = isRestoring() + return { + getSnapshot: () => { + const results = observer.getOptimisticResult( + defaultedQueries(), + undefined, + )[0] + refetches.length = results.length + return results.map((result, index) => ({ + ...result, + refetch: getRefetch(index), + })) + }, + subscribe: restoring + ? undefined + : (onStoreChange) => { + const unsubscribe = observer.subscribe(() => { + if (lifecycle.destroyed) return + onStoreChange() + }) + return () => { + lifecycle.setPending(false) + unsubscribe() + } + }, + } + }) + + effect((onCleanup) => { + const results = resultSignal() + if (isRestoring()) { + lifecycle.setPending(false) + return + } + + lifecycle.setPending(shouldBlockPendingTasks(observerSignal(), results)) + onCleanup(() => lifecycle.setPending(false)) + }) + + const createResultProxy = (index: number) => { + const resultAtIndexSignal = computed(() => resultSignal()[index]!) + return Object.assign(signalProxy(resultAtIndexSignal, queryResultFields), { + refetch: getRefetch(index), + }) + } + + const resultProxies: Array> = [] + const proxiedResultsSignal = computed(() => { + const results = resultSignal() + resultProxies.length = results.length + + return results.map((_, index) => { + return (resultProxies[index] ??= createResultProxy(index)) + }) + }) + + // Combine in Angular's tracked computation. Core must notify for every raw + // result change, including changes a previous combine function ignored. + return computed(() => { + const result = resultSignal() + const { combine } = optionsSignal() + + if (combine) + return combine(result as Parameters>[0]) + + return proxiedResultsSignal() as unknown as TCombinedResult + }) as unknown as Signal +} diff --git a/packages/angular-query/src/inject-queries.types.ts b/packages/angular-query/src/inject-queries.types.ts new file mode 100644 index 00000000000..ce6f9cd8da0 --- /dev/null +++ b/packages/angular-query/src/inject-queries.types.ts @@ -0,0 +1,223 @@ +import type { + DefaultError, + DefinedQueryObserverResult, + OmitKeyof, + QueriesPlaceholderDataFunction, + QueryFunction, + QueryKey, + QueryObserverResult, + dataTagErrorSymbol, +} from '@tanstack/query-core' +import type { + CreateQueryOptions, + CreateQueryResult, + DefinedCreateQueryResult, +} from './types' + +type QueryObserverOptionsForCreateQueries< + TQueryFnData = unknown, + TError = DefaultError, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +> = OmitKeyof< + CreateQueryOptions, + 'placeholderData' +> & { + placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction +} + +type QueryError = T extends { + queryKey: { [dataTagErrorSymbol]: infer TError } +} + ? TError + : T extends CreateQueryOptions + ? unknown extends TError + ? DefaultError + : TError + : DefaultError + +type MAXIMUM_DEPTH = 20 +type SkipTokenForCreateQueries = symbol + +type GetCreateQueryOptionsForCreateQueries = T extends { + queryFnData: infer TQueryFnData + error?: infer TError + data: infer TData +} + ? QueryObserverOptionsForCreateQueries + : T extends { queryFnData: infer TQueryFnData; error?: infer TError } + ? QueryObserverOptionsForCreateQueries + : T extends { data: infer TData; error?: infer TError } + ? QueryObserverOptionsForCreateQueries + : T extends [infer TQueryFnData, infer TError, infer TData] + ? QueryObserverOptionsForCreateQueries + : T extends [infer TQueryFnData, infer TError] + ? QueryObserverOptionsForCreateQueries + : T extends [infer TQueryFnData] + ? QueryObserverOptionsForCreateQueries + : T extends { + queryFn?: + | QueryFunction + | SkipTokenForCreateQueries + select?: (data: any) => infer TData + } + ? QueryObserverOptionsForCreateQueries< + TQueryFnData, + QueryError, + unknown extends TData ? TQueryFnData : TData, + TQueryKey + > + : QueryObserverOptionsForCreateQueries + +type GenericGetDefinedOrUndefinedQueryResult = + T extends { initialData?: infer TInitialData } + ? unknown extends TInitialData + ? TUndefined + : TInitialData extends TData + ? TDefined + : TInitialData extends () => infer TInitialDataResult + ? unknown extends TInitialDataResult + ? TUndefined + : TInitialDataResult extends TData + ? TDefined + : TUndefined + : TUndefined + : TUndefined + +type InferDataAndError = T extends { + queryFnData: any + error?: infer TError + data: infer TData +} + ? { data: TData; error: TError } + : T extends { queryFnData: infer TQueryFnData; error?: infer TError } + ? { data: TQueryFnData; error: TError } + : T extends { data: infer TData; error?: infer TError } + ? { data: TData; error: TError } + : T extends [any, infer TError, infer TData] + ? { data: TData; error: TError } + : T extends [infer TQueryFnData, infer TError] + ? { data: TQueryFnData; error: TError } + : T extends [infer TQueryFnData] + ? { data: TQueryFnData; error: unknown } + : T extends { + queryFn?: + | QueryFunction + | SkipTokenForCreateQueries + select?: (data: any) => infer TData + } + ? { + data: unknown extends TData ? TQueryFnData : TData + error: QueryError + } + : { data: unknown; error: DefaultError } + +type GetCreateQueryResult = GenericGetDefinedOrUndefinedQueryResult< + T, + InferDataAndError['data'], + CreateQueryResult< + InferDataAndError['data'], + InferDataAndError['error'] + >, + DefinedCreateQueryResult< + InferDataAndError['data'], + InferDataAndError['error'] + > +> + +type GetQueryObserverResult = GenericGetDefinedOrUndefinedQueryResult< + T, + InferDataAndError['data'], + QueryObserverResult< + InferDataAndError['data'], + InferDataAndError['error'] + >, + DefinedQueryObserverResult< + InferDataAndError['data'], + InferDataAndError['error'] + > +> + +export type QueriesOptions< + T extends Array, + TResults extends Array = [], + TDepth extends ReadonlyArray = [], +> = TDepth['length'] extends MAXIMUM_DEPTH + ? Array + : T extends [] + ? [] + : T extends [infer Head] + ? [...TResults, GetCreateQueryOptionsForCreateQueries] + : T extends [infer Head, ...infer Tails] + ? QueriesOptions< + [...Tails], + [...TResults, GetCreateQueryOptionsForCreateQueries], + [...TDepth, 1] + > + : ReadonlyArray extends T + ? T + : T extends Array< + QueryObserverOptionsForCreateQueries< + infer TQueryFnData, + infer TError, + infer TData, + infer TQueryKey + > + > + ? Array< + QueryObserverOptionsForCreateQueries< + TQueryFnData, + TError, + TData, + TQueryKey + > + > + : Array + +export type QueriesResults< + T extends Array, + TResults extends Array = [], + TDepth extends ReadonlyArray = [], +> = TDepth['length'] extends MAXIMUM_DEPTH + ? Array + : T extends [] + ? [] + : T extends [infer Head] + ? [...TResults, GetCreateQueryResult] + : T extends [infer Head, ...infer Tails] + ? QueriesResults< + [...Tails], + [...TResults, GetCreateQueryResult], + [...TDepth, 1] + > + : { [K in keyof T]: GetCreateQueryResult } + +type RawQueriesResults< + T extends Array, + TResults extends Array = [], + TDepth extends ReadonlyArray = [], +> = TDepth['length'] extends MAXIMUM_DEPTH + ? Array + : T extends [] + ? [] + : T extends [infer Head] + ? [...TResults, GetQueryObserverResult] + : T extends [infer Head, ...infer Tails] + ? RawQueriesResults< + [...Tails], + [...TResults, GetQueryObserverResult], + [...TDepth, 1] + > + : { [K in keyof T]: GetQueryObserverResult } + +export interface InjectQueriesOptions< + T extends Array, + TCombinedResult = QueriesResults, +> { + queries: + | readonly [...QueriesOptions] + | readonly [ + ...{ [K in keyof T]: GetCreateQueryOptionsForCreateQueries }, + ] + combine?: (result: RawQueriesResults) => TCombinedResult +} diff --git a/packages/angular-query-experimental/src/inject-query.ts b/packages/angular-query/src/inject-query.ts similarity index 75% rename from packages/angular-query-experimental/src/inject-query.ts rename to packages/angular-query/src/inject-query.ts index 973538ca053..f2dfe752971 100644 --- a/packages/angular-query-experimental/src/inject-query.ts +++ b/packages/angular-query/src/inject-query.ts @@ -1,12 +1,14 @@ import { QueryObserver } from '@tanstack/query-core' -import { - Injector, - assertInInjectionContext, - inject, - runInInjectionContext, -} from '@angular/core' -import { createBaseQuery } from './create-base-query' -import type { DefaultError, QueryKey } from '@tanstack/query-core' +import { assertInInjectionContext, untracked } from '@angular/core' +import { injectQueryZone } from './utils/inject-query-zone' +import { injectBaseQuery } from './inject-base-query' +import { signalProxy } from './utils/signal-proxy' +import { queryResultFields } from './utils/result-fields' +import type { + DefaultError, + QueryKey, + RefetchOptions, +} from '@tanstack/query-core' import type { CreateQueryOptions, CreateQueryResult, @@ -17,26 +19,16 @@ import type { UndefinedInitialDataOptions, } from './query-options' -export interface InjectQueryOptions { - /** - * The `Injector` in which to create the query. - * - * If this is not provided, the current injection context will be used instead (via `inject`). - */ - injector?: Injector -} - /** - * This overload is selected when `initialData` is set on the options returned by `injectQueryFn`, so the + * This overload is selected when `initialData` is set on the options returned by `optionsFn`, so the * resulting `data` signal is never `undefined` (unless a `select` changes `TData` to include `undefined`). * * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries * @see {@link queryOptions} to share these options between `injectQuery` and imperative APIs like - * `queryClient.fetchQuery`. - * @param injectQueryFn - A function returning the {@link DefinedInitialDataOptions} to use — everything you + * `queryClient.query`. + * @param optionsFn - A function returning the {@link DefinedInitialDataOptions} to use — everything you * can pass to `injectQuery`, with `initialData` set. Similar to `computed` from Angular, this function runs * in the reactive context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive the query. - * @param options - Additional configuration * @returns The query result, typed so that `data` is never `undefined` (unless a `select` changes `TData` to * include `undefined`). * @@ -72,13 +64,12 @@ export function injectQuery< TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, >( - injectQueryFn: () => DefinedInitialDataOptions< + optionsFn: () => DefinedInitialDataOptions< TQueryFnData, TError, TData, TQueryKey >, - options?: InjectQueryOptions, ): DefinedCreateQueryResult /** @@ -86,11 +77,10 @@ export function injectQuery< * * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries * @see {@link queryOptions} to share these options between `injectQuery` and imperative APIs like - * `queryClient.fetchQuery`. - * @param injectQueryFn - A function returning the {@link UndefinedInitialDataOptions} to use — everything + * `queryClient.query`. + * @param optionsFn - A function returning the {@link UndefinedInitialDataOptions} to use — everything * you can pass to `injectQuery`. Similar to `computed` from Angular, this function runs in the reactive * context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive the query. - * @param options - Additional configuration * @returns The query result. `status()` is `'pending'` if there is no cached data to display, `'error'` if * the last fetch attempt failed, or `'success'` if the query has data to display. `isPending`/`isSuccess`/ * `isError` are type-guard methods for convenience. @@ -149,7 +139,6 @@ export function injectQuery< * readonly postsQuery = injectQuery(() => ({ * queryKey: ['posts', this.filter()], * queryFn: () => fetchPosts(this.filter()), - * // Signals can be combined with expressions * enabled: !!this.filter(), * })) * } @@ -161,13 +150,12 @@ export function injectQuery< TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, >( - injectQueryFn: () => UndefinedInitialDataOptions< + optionsFn: () => UndefinedInitialDataOptions< TQueryFnData, TError, TData, TQueryKey >, - options?: InjectQueryOptions, ): CreateQueryResult /** @@ -176,10 +164,8 @@ export function injectQuery< * `injectQuery` in your own helper function that forwards caller-provided options. * * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries - * @param injectQueryFn - A function that returns query options. Similar to `computed` from Angular, this - * function runs in the reactive context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive - * the query. - * @param options - Additional configuration + * @param optionsFn - A function that returns query options. Similar to `computed` from Angular, this + * function runs in the reactive context, so signals read inside it drive the query. * @returns The query result. */ export function injectQuery< @@ -188,21 +174,19 @@ export function injectQuery< TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, >( - injectQueryFn: () => CreateQueryOptions< - TQueryFnData, - TError, - TData, - TQueryKey - >, - options?: InjectQueryOptions, + optionsFn: () => CreateQueryOptions, ): CreateQueryResult export function injectQuery( - injectQueryFn: () => CreateQueryOptions, - options?: InjectQueryOptions, -) { - !options?.injector && assertInInjectionContext(injectQuery) - return runInInjectionContext(options?.injector ?? inject(Injector), () => - createBaseQuery(injectQueryFn, QueryObserver), - ) as unknown as CreateQueryResult + optionsFn: () => CreateQueryOptions, +): DefinedCreateQueryResult | CreateQueryResult { + if (typeof ngDevMode === 'undefined' || ngDevMode) { + assertInInjectionContext(injectQuery) + } + const outsideZone = injectQueryZone() + const [resultSignal, getObserver] = injectBaseQuery(optionsFn, QueryObserver) + return Object.assign(signalProxy(resultSignal, queryResultFields), { + refetch: (options?: RefetchOptions) => + outsideZone(() => untracked(() => getObserver().refetch(options))), + }) as unknown as DefinedCreateQueryResult | CreateQueryResult } diff --git a/packages/angular-query/src/internal.ts b/packages/angular-query/src/internal.ts new file mode 100644 index 00000000000..b975e19381b --- /dev/null +++ b/packages/angular-query/src/internal.ts @@ -0,0 +1,8 @@ +/** + * Internal APIs shared by the Angular Query packages. + * + * This entry point is not part of the application-facing API and may change + * without notice. + */ +export { getQueryFeatureProviders, queryFeature } from './providers' +export { provideIsRestoring } from './inject-is-restoring' diff --git a/packages/angular-query-experimental/src/mutation-options.ts b/packages/angular-query/src/mutation-options.ts similarity index 98% rename from packages/angular-query-experimental/src/mutation-options.ts rename to packages/angular-query/src/mutation-options.ts index 9f16afab09f..89b521bdc44 100644 --- a/packages/angular-query-experimental/src/mutation-options.ts +++ b/packages/angular-query/src/mutation-options.ts @@ -14,7 +14,7 @@ import type { CreateMutationOptions } from './types' * @example * Looking the mutation up elsewhere via its `mutationKey`, e.g. for a global "saving…" indicator: * ```angular-ts - * import { mutationOptions, injectMutationState } from '@tanstack/angular-query-experimental' + * import { mutationOptions, injectMutationState } from '@tanstack/angular-query' * * const createPostOptions = mutationOptions({ * mutationKey: ['posts', 'create'], @@ -66,7 +66,7 @@ export function mutationOptions< * @example * Sharing options across services, so `QueriesService` stays the single place a mutation is defined: * ```angular-ts - * import { mutationOptions, injectMutation } from '@tanstack/angular-query-experimental' + * import { mutationOptions, injectMutation } from '@tanstack/angular-query' * * @Injectable({ providedIn: 'root' }) * export class QueriesService { diff --git a/packages/angular-query/src/providers.ts b/packages/angular-query/src/providers.ts new file mode 100644 index 00000000000..98c681d332f --- /dev/null +++ b/packages/angular-query/src/providers.ts @@ -0,0 +1,192 @@ +import { isPlatformBrowser, isPlatformServer } from '@angular/common' +import { + DOCUMENT, + DestroyRef, + InjectionToken, + PLATFORM_ID, + TransferState, + inject, + makeEnvironmentProviders, + makeStateKey, + provideEnvironmentInitializer, +} from '@angular/core' +import { QueryClient, dehydrate, hydrate } from '@tanstack/query-core' +import { INTERNAL_TANSTACK_QUERY_HYDRATION_TRANSFER_KEY } from './hydration-state-key' +import { injectQueryZone } from './utils/inject-query-zone' +import type { DehydratedState } from '@tanstack/query-core' +import type { EnvironmentProviders } from '@angular/core' + +const INTERNAL_QUERY_CLIENT_SHOULD_HYDRATE = new InjectionToken('', { + providedIn: 'root', + factory: () => true, +}) + +function configureQueryClient() { + const queryClient = inject(QueryClient) + const destroyRef = inject(DestroyRef) + const platformId = inject(PLATFORM_ID) + + if (isPlatformServer(platformId)) { + // DOM emulation can fool core's runtime detection. Apply server defaults to + // this client without changing other clients or global scheduling providers. + const defaults = queryClient.getDefaultOptions() + queryClient.setDefaultOptions({ + ...defaults, + queries: { gcTime: Infinity, retry: false, ...defaults.queries }, + mutations: { gcTime: Infinity, ...defaults.mutations }, + }) + } + const shouldHydrate = inject(INTERNAL_QUERY_CLIENT_SHOULD_HYDRATE) + const hydrationStateKey = inject( + INTERNAL_TANSTACK_QUERY_HYDRATION_TRANSFER_KEY, + ) + + if (inject(DOCUMENT, { optional: true })) { + const transferState = inject(TransferState) + + if (shouldHydrate && isPlatformServer(platformId)) { + transferState.onSerialize(hydrationStateKey, () => dehydrate(queryClient)) + } else if (shouldHydrate && isPlatformBrowser(platformId)) { + const dehydratedState = transferState.get(hydrationStateKey, null) + if (dehydratedState) { + hydrate(queryClient, dehydratedState) + transferState.remove(hydrationStateKey) + } + } + } + + queryClient.mount() + destroyRef.onDestroy(() => queryClient.unmount()) +} + +/** + * Provides a `QueryClient` and optional TanStack Query features. + * The factory runs once per injector in Angular's injection context, so it can + * call `inject()` and each SSR request can receive an independent cache. + * + * **Example - standalone** + * + * @example + * ```ts + * import { + * provideTanStackQuery, + * QueryClient, + * } from '@tanstack/angular-query' + * + * bootstrapApplication(AppComponent, { + * providers: [provideTanStackQuery(() => new QueryClient())], + * }) + * ``` + * + * You can also enable optional developer tools by adding `withDevtools`. By + * default the tools will then be loaded when your app is in development mode. + * + * ```ts + * import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query' + * import { withDevtools } from '@tanstack/angular-query-devtools' + * + * bootstrapApplication(AppComponent, { + * providers: [ + * provideTanStackQuery(() => new QueryClient(), withDevtools()), + * ], + * }) + * ``` + * + * @param queryClientFactory - Creates or resolves a `QueryClient` in the injection context. + * @param features - Optional features to configure additional Query functionality. + * @returns A single {@link EnvironmentProviders} value (do not spread into `providers`). + * @see https://tanstack.com/query/v5/docs/framework/angular/quick-start + * @see https://tanstack.com/query/v5/docs/framework/angular/devtools + * @see https://tanstack.com/query/latest/docs/framework/angular/guides/ssr + */ +export function provideTanStackQuery( + queryClientFactory: () => QueryClient, + ...features: ReadonlyArray +): EnvironmentProviders { + return makeEnvironmentProviders([ + { + provide: QueryClient, + useFactory: () => injectQueryZone()(queryClientFactory), + }, + ...features.map(getQueryFeatureProviders), + provideEnvironmentInitializer(configureQueryClient), + ]) +} + +const queryFeatureBrand: unique symbol = Symbol('QueryFeature') + +/** + * Opaque configuration returned by Query feature functions such as `withHydrationKey`. + * Pass features to `provideTanStackQuery`; applications do not construct them directly. + */ +export interface QueryFeature { + /** @internal */ + readonly [queryFeatureBrand]: true +} + +interface InternalQueryFeature extends QueryFeature { + readonly ɵproviders: EnvironmentProviders +} + +/** + * Creates a feature shared by Angular Query integration packages. + * @internal + * @param providers - + * @returns A Query feature. + */ +export function queryFeature(providers: EnvironmentProviders): QueryFeature { + const feature: InternalQueryFeature = { + [queryFeatureBrand]: true, + ɵproviders: providers, + } + + return feature +} + +/** @internal */ +export function getQueryFeatureProviders( + feature: QueryFeature, +): EnvironmentProviders { + return (feature as InternalQueryFeature).ɵproviders +} + +/** + * Sets a non-default serialization key for this injector's `QueryClient` cache (server dehydrate / + * browser hydrate via `TransferState`). Use this when you have multiple `QueryClient` instances + * so each has its own key. The default key applies when you do not add this feature. + * + * ```ts + * providers: [ + * provideTanStackQuery( + * () => new QueryClient(), + * withHydrationKey('my-secondary-query-cache'), + * ), + * ] + * ``` + * + * @param key - A unique string for this client's `TransferState` entry. + */ +export function withHydrationKey(key: string): QueryFeature { + return queryFeature( + makeEnvironmentProviders([ + { + provide: INTERNAL_TANSTACK_QUERY_HYDRATION_TRANSFER_KEY, + useValue: makeStateKey(key), + }, + ]), + ) +} + +/** + * Disables `TransferState` hydration and dehydration for the current environment injector. + */ +export function withNoQueryHydration(): QueryFeature { + return queryFeature( + makeEnvironmentProviders([ + { + provide: INTERNAL_QUERY_CLIENT_SHOULD_HYDRATE, + useValue: false, + }, + ]), + ) +} diff --git a/packages/angular-query-experimental/src/query-options.ts b/packages/angular-query/src/query-options.ts similarity index 89% rename from packages/angular-query-experimental/src/query-options.ts rename to packages/angular-query/src/query-options.ts index 0de61895e72..841c943b2ac 100644 --- a/packages/angular-query-experimental/src/query-options.ts +++ b/packages/angular-query/src/query-options.ts @@ -3,7 +3,6 @@ import type { InitialDataFunction, NonUndefinedGuard, OmitKeyof, - QueryFunction, QueryKey, QueryKeyWithDataTag, SkipToken, @@ -82,31 +81,15 @@ export type DefinedInitialDataOptions< TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, -> = Omit< - CreateQueryOptions, - 'queryFn' -> & { - /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. - */ +> = CreateQueryOptions & { initialData: | NonUndefinedGuard | (() => NonUndefinedGuard) - /** - * Optional here, but omitting it is only safe when no fetch will be attempted — for example with - * `enabled: false`, or when a default query function has been defined. Otherwise, an enabled query with no - * `queryFn` still tries to fetch and fails with a "Missing queryFn" error; `initialData` does not prevent this. - */ - queryFn?: QueryFunction } /** * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options - * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is + * can be shared across functions and imperative APIs such as `queryClient.query`. `options.queryKey` is * required and is the query key to generate options for. * * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless @@ -120,7 +103,7 @@ export type DefinedInitialDataOptions< * * @example * ```angular-ts - * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' + * import { queryOptions, injectQuery } from '@tanstack/angular-query' * * export const postsOptions = queryOptions({ * queryKey: ['posts'], @@ -160,7 +143,7 @@ export function queryOptions< /** * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options - * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is + * can be shared across functions and imperative APIs such as `queryClient.query`. `options.queryKey` is * required and is the query key to generate options for. * * @see {@link injectQuery} to run a query with these options. @@ -171,7 +154,7 @@ export function queryOptions< * @example * A parameterized factory, so the same options object can be reused per `id`: * ```angular-ts - * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' + * import { queryOptions, injectQuery } from '@tanstack/angular-query' * * export const postOptions = (id: string) => * queryOptions({ @@ -209,7 +192,7 @@ export function queryOptions< /** * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options - * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is + * can be shared across functions and imperative APIs such as `queryClient.query`. `options.queryKey` is * required and is the query key to generate options for. * * @see {@link injectQuery} to run a query with these options. @@ -221,7 +204,7 @@ export function queryOptions< * @example * A parameterized factory, so the same options object can be reused per `id`: * ```angular-ts - * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' + * import { queryOptions, injectQuery } from '@tanstack/angular-query' * * export const postOptions = (id: string) => * queryOptions({ @@ -250,7 +233,7 @@ export function queryOptions< * @example * A factory that disables the query, type safe, until `postId` is set: * ```angular-ts - * import { queryOptions, skipToken, injectQuery } from '@tanstack/angular-query-experimental' + * import { queryOptions, skipToken, injectQuery } from '@tanstack/angular-query' * * export const postOptions = (postId: number | undefined) => * queryOptions({ diff --git a/packages/angular-query/src/query-resource.ts b/packages/angular-query/src/query-resource.ts new file mode 100644 index 00000000000..33f47894cc5 --- /dev/null +++ b/packages/angular-query/src/query-resource.ts @@ -0,0 +1,137 @@ +import { computed, untracked } from '@angular/core' +import type { QueryObserverResult } from '@tanstack/query-core' +import type { ResourceSnapshot } from './utils/resource-types' +import type { Resource, ResourceStatus, Signal } from '@angular/core' + +export interface QueryResource extends Resource { + /** + * The current query state as a single snapshot. + */ + readonly snapshot: Signal> + + /** + * Requests a new query fetch only when the current query data is stale. + * + * Used for compatibility with Angular APIs that might want to reload a resource, + * like Signal Forms' validateAsync resource interface. + * + * @returns `true` if a reload was initiated, `false` if a reload was unnecessary or unsupported. + */ + reload: () => boolean +} + +type QueryResourceSource = { + readonly data: Signal + readonly status: Signal + readonly fetchStatus: Signal + readonly error: Signal + readonly isStale: Signal + readonly refetch: () => unknown +} + +/** + * Converts an Angular Query result into Angular's Resource interface. + * + * Call this function once and reuse the returned resource. + * + * @param query An Angular Query or infinite-query result. + * @returns A Resource-compatible view of the query result. + */ +export function toResource( + query: QueryResourceSource, +): QueryResource { + // Intentionally does not use resource from snapshot to have + // support for the reload method for compatible libraries + const status = computed(() => { + const fetchStatus = query.fetchStatus() + const data = query.data() + + if (fetchStatus === 'fetching' || fetchStatus === 'paused') { + return data === undefined ? 'loading' : 'reloading' + } + + switch (query.status()) { + case 'success': + return 'resolved' + case 'error': + return 'error' + case 'pending': + return 'idle' + } + }) + + const error = computed(() => { + return query.status() === 'error' + ? normalizeError(query.error()) + : undefined + }) + + const value = computed(() => { + if (status() === 'error') { + throw error() + } + + return query.data() + }) + + const snapshot = computed>(() => { + const currentStatus = status() + + if (currentStatus === 'error') { + return { status: 'error', error: error()! } + } + + return { status: currentStatus, value: query.data() } + }) + + const hasValue = (() => + status() !== 'error' && + query.data() !== undefined) as QueryResource['hasValue'] + + return { + value, + status, + error, + snapshot, + isLoading: computed(() => { + const currentStatus = status() + return currentStatus === 'loading' || currentStatus === 'reloading' + }), + hasValue, + reload(): boolean { + const currentStatus = untracked(status) + if ( + currentStatus === 'idle' || + currentStatus === 'loading' || + currentStatus === 'reloading' + ) { + return false + } + + if (!untracked(query.isStale)) { + return false + } + + void query.refetch() + return true + }, + } +} + +function normalizeError(error: unknown): Error { + if (isErrorLike(error)) { + return error + } + + return new Error(String(error), { cause: error }) +} + +function isErrorLike(error: unknown): error is Error { + return ( + error instanceof Error || + (typeof error === 'object' && + error !== null && + typeof (error as Error).name === 'string' && + typeof (error as Error).message === 'string') + ) +} diff --git a/packages/angular-query-experimental/src/types.ts b/packages/angular-query/src/types.ts similarity index 68% rename from packages/angular-query-experimental/src/types.ts rename to packages/angular-query/src/types.ts index b0acd8579fc..2bdde723202 100644 --- a/packages/angular-query-experimental/src/types.ts +++ b/packages/angular-query/src/types.ts @@ -16,54 +16,19 @@ import type { QueryObserverResult, } from '@tanstack/query-core' import type { Signal } from '@angular/core' -import type { MapToSignals } from './signal-proxy' +import type { MapToSignals, MethodKeys } from './utils/signal-proxy' -/** - * The options shared across `angular-query-experimental`'s query functions. Extends - * {@link QueryObserverOptions} from `@tanstack/query-core` as-is — unlike `react-query`, - * `angular-query-experimental` has no extra framework-specific option here. - * - * @template TQueryFnData - The type your `queryFn` resolves to. - * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no - * `select` is used. - * @template TQueryData - The type of the data actually held in the query cache — the input to `select` and - * `placeholderData`. Defaults to, and is usually the same as, `TQueryFnData`. - * @template TQueryKey - The type of your `queryKey`. - */ -export interface CreateBaseQueryOptions< - TQueryFnData = unknown, - TError = DefaultError, - TData = TQueryFnData, - TQueryData = TQueryFnData, - TQueryKey extends QueryKey = QueryKey, -> extends QueryObserverOptions< - TQueryFnData, - TError, - TData, - TQueryData, - TQueryKey -> {} +type SignalFunction any> = T & Signal> -/** - * The options accepted by `injectQuery`. Same as {@link CreateBaseQueryOptions}, minus `suspense` — which - * `angular-query-experimental` doesn't support, unlike `react-query`. - * - * @template TQueryFnData - The type your `queryFn` resolves to. - * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no - * `select` is used. - * @template TQueryKey - The type of your `queryKey`. - */ -export interface CreateQueryOptions< +export type CreateQueryOptions< TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, -> extends OmitKeyof< - CreateBaseQueryOptions, - 'suspense' -> {} +> = OmitKeyof< + QueryObserverOptions, + 'notifyOnChangeProps' | 'suspense' | 'throwOnError' +> type CreateStatusBasedQueryResult< TStatus extends QueryObserverResult['status'], @@ -71,53 +36,141 @@ type CreateStatusBasedQueryResult< TError = DefaultError, > = Extract, { status: TStatus }> -/** - * The `isSuccess`/`isError`/`isPending` methods on a query result. Unlike `react-query`'s derived booleans, - * these are type-guard methods you call — `if (query.isSuccess())` — so that `query.data` narrows away - * `undefined` inside the branch, the same way `status` narrowing works on the plain object `react-query` - * returns. - * - * @template TData - The type `data` ends up as after `select` runs. - * @template TError - The type of errors your `queryFn` may throw. - */ +type CreateStatusBasedDefinedQueryResult< + TStatus extends DefinedQueryObserverResult['status'], + TData = unknown, + TError = DefaultError, +> = Extract, { status: TStatus }> + +type CreateStatusBasedInfiniteQueryResult< + TStatus extends InfiniteQueryObserverResult['status'], + TData = unknown, + TError = DefaultError, +> = Extract, { status: TStatus }> + +type CreateStatusBasedDefinedInfiniteQueryResult< + TStatus extends DefinedInfiniteQueryObserverResult['status'], + TData = unknown, + TError = DefaultError, +> = Extract< + DefinedInfiniteQueryObserverResult, + { status: TStatus } +> + export interface BaseQueryNarrowing { - isSuccess: ( - this: CreateBaseQueryResult, - ) => this is CreateBaseQueryResult< - TData, - TError, - CreateStatusBasedQueryResult<'success', TData, TError> + isSuccess: SignalFunction< + ( + this: CreateBaseQueryResult, + ) => this is CreateBaseQueryResult< + TData, + TError, + CreateStatusBasedQueryResult<'success', TData, TError> + > > - isError: ( - this: CreateBaseQueryResult, - ) => this is CreateBaseQueryResult< - TData, - TError, - CreateStatusBasedQueryResult<'error', TData, TError> + isError: SignalFunction< + ( + this: CreateBaseQueryResult, + ) => this is CreateBaseQueryResult< + TData, + TError, + CreateStatusBasedQueryResult<'error', TData, TError> + > > - isPending: ( - this: CreateBaseQueryResult, - ) => this is CreateBaseQueryResult< - TData, - TError, - CreateStatusBasedQueryResult<'pending', TData, TError> + isPending: SignalFunction< + ( + this: CreateBaseQueryResult, + ) => this is CreateBaseQueryResult< + TData, + TError, + CreateStatusBasedQueryResult<'pending', TData, TError> + > + > +} + +export interface DefinedQueryNarrowing { + isSuccess: SignalFunction< + ( + this: DefinedCreateQueryResult, + ) => this is DefinedCreateQueryResult< + TData, + TError, + CreateStatusBasedDefinedQueryResult<'success', TData, TError> + > + > + isError: SignalFunction< + ( + this: DefinedCreateQueryResult, + ) => this is DefinedCreateQueryResult< + TData, + TError, + CreateStatusBasedDefinedQueryResult<'error', TData, TError> + > + > + isPending: SignalFunction< + (this: DefinedCreateQueryResult) => this is never + > +} + +export interface BaseInfiniteQueryNarrowing< + TData = unknown, + TError = DefaultError, +> { + isSuccess: SignalFunction< + ( + this: CreateInfiniteQueryResult, + ) => this is CreateInfiniteQueryResult< + TData, + TError, + CreateStatusBasedInfiniteQueryResult<'success', TData, TError> + > + > + isError: SignalFunction< + ( + this: CreateInfiniteQueryResult, + ) => this is CreateInfiniteQueryResult< + TData, + TError, + CreateStatusBasedInfiniteQueryResult<'error', TData, TError> + > + > + isPending: SignalFunction< + ( + this: CreateInfiniteQueryResult, + ) => this is CreateInfiniteQueryResult< + TData, + TError, + CreateStatusBasedInfiniteQueryResult<'pending', TData, TError> + > + > +} + +export interface DefinedInfiniteQueryNarrowing< + TData = unknown, + TError = DefaultError, +> { + isSuccess: SignalFunction< + ( + this: DefinedCreateInfiniteQueryResult, + ) => this is DefinedCreateInfiniteQueryResult< + TData, + TError, + CreateStatusBasedDefinedInfiniteQueryResult<'success', TData, TError> + > + > + isError: SignalFunction< + ( + this: DefinedCreateInfiniteQueryResult, + ) => this is DefinedCreateInfiniteQueryResult< + TData, + TError, + CreateStatusBasedDefinedInfiniteQueryResult<'error', TData, TError> + > + > + isPending: SignalFunction< + (this: DefinedCreateInfiniteQueryResult) => this is never > } -/** - * The options accepted by `injectInfiniteQuery`. Same as {@link CreateBaseQueryOptions}, minus `suspense` — - * which `angular-query-experimental` doesn't support, unlike `react-query` — extends - * {@link InfiniteQueryObserverOptions} from `@tanstack/query-core` for the infinite-query-specific options - * (`getNextPageParam`, `initialPageParam`, etc.). - * - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. - * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` here, though - * `injectInfiniteQuery` itself defaults it to `InfiniteData` — the shape `data` actually has - * when no `select` is used. - * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. - */ export interface CreateInfiniteQueryOptions< TQueryFnData = unknown, TError = DefaultError, @@ -132,7 +185,7 @@ export interface CreateInfiniteQueryOptions< TQueryKey, TPageParam >, - 'suspense' + 'notifyOnChangeProps' | 'suspense' | 'throwOnError' > {} /** @@ -149,9 +202,15 @@ export interface CreateInfiniteQueryOptions< export type CreateBaseQueryResult< TData = unknown, TError = DefaultError, - TState = QueryObserverResult, + TState extends QueryObserverResult = QueryObserverResult< + TData, + TError + >, > = BaseQueryNarrowing & - MapToSignals> + MapToSignals< + OmitKeyof, + MethodKeys> + > /** * The result of `injectQuery`. Same as {@link CreateBaseQueryResult}. @@ -175,9 +234,13 @@ export type CreateQueryResult< export type DefinedCreateQueryResult< TData = unknown, TError = DefaultError, - TState = DefinedQueryObserverResult, -> = BaseQueryNarrowing & - MapToSignals> + TState extends DefinedQueryObserverResult = + DefinedQueryObserverResult, +> = DefinedQueryNarrowing & + MapToSignals< + OmitKeyof, + MethodKeys> + > /** * The result of `injectInfiniteQuery` when `initialData` isn't set — `data` may be `undefined` while the @@ -191,8 +254,10 @@ export type DefinedCreateQueryResult< export type CreateInfiniteQueryResult< TData = unknown, TError = DefaultError, -> = BaseQueryNarrowing & - MapToSignals> + TState extends InfiniteQueryObserverResult = + InfiniteQueryObserverResult, +> = BaseInfiniteQueryNarrowing & + MapToSignals> /** * The result of `injectInfiniteQuery` when `initialData` is set — `data` is never `undefined`. Same shape as @@ -205,11 +270,15 @@ export type CreateInfiniteQueryResult< export type DefinedCreateInfiniteQueryResult< TData = unknown, TError = DefaultError, - TDefinedInfiniteQueryObserver = DefinedInfiniteQueryObserverResult< + TDefinedInfiniteQueryObserver extends DefinedInfiniteQueryObserverResult< TData, TError - >, -> = MapToSignals + > = DefinedInfiniteQueryObserverResult, +> = DefinedInfiniteQueryNarrowing & + MapToSignals< + TDefinedInfiniteQueryObserver, + MethodKeys + > /** * The options accepted by `injectMutation`. Same as {@link MutationObserverOptions} from @@ -228,7 +297,7 @@ export interface CreateMutationOptions< TOnMutateResult = unknown, > extends OmitKeyof< MutationObserverOptions, - '_defaulted' + '_defaulted' | 'throwOnError' > {} /** @@ -312,19 +381,6 @@ type CreateStatusBasedMutationResult< { status: TStatus } > -type SignalFunction any> = T & Signal> - -/** - * The `isSuccess`/`isError`/`isPending`/`isIdle` methods on a mutation result. Each is both a `Signal` - * (its current boolean value is read reactively without calling it) and a type-guard function you can - * call — `if (mutation.isSuccess())` — so that `mutation.data` narrows away `undefined` inside the branch. - * - * @template TData - The type your mutation function resolves to. - * @template TError - The type of errors your mutation function may throw. - * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. - */ export interface BaseMutationNarrowing< TData = unknown, TError = DefaultError, @@ -426,4 +482,7 @@ export type CreateMutationResult< TOnMutateResult >, > = BaseMutationNarrowing & - MapToSignals> + MapToSignals< + OmitKeyof, + MethodKeys> + > diff --git a/packages/angular-query/src/utils/__test__/inject-external-store.test.ts b/packages/angular-query/src/utils/__test__/inject-external-store.test.ts new file mode 100644 index 00000000000..d8d8c1e7011 --- /dev/null +++ b/packages/angular-query/src/utils/__test__/inject-external-store.test.ts @@ -0,0 +1,272 @@ +import { Component, computed, input, inputBinding, signal } from '@angular/core' +import { TestBed } from '@angular/core/testing' +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { injectExternalStore } from '../inject-external-store' +import { provideAngularQueryChangeDetection } from '../../__tests__/test-utils' +import type { Signal } from '@angular/core' + +function store(initial: number) { + let current = initial + const listeners = new Set<() => void>() + const cleanup = vi.fn((notify: () => void) => listeners.delete(notify)) + const subscribe = vi.fn((notify: () => void) => { + listeners.add(notify) + return () => cleanup(notify) + }) + return { + subscribe, + cleanup, + getSnapshot: () => current, + set(next: number) { + current = next + listeners.forEach((notify) => notify()) + }, + } +} + +function host( + create: () => Signal, + initialize?: (value: Signal) => void, +) { + @Component({ template: '' }) + class Host { + readonly value = create() + ngOnInit() { + initialize?.(this.value) + } + } + return TestBed.createComponent(Host) +} + +describe('injectExternalStore', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [provideAngularQueryChangeDetection()], + }) + }) + + it('reflects changes made during initialization after an early snapshot read', () => { + const source = store(1) + const fixture = host( + () => injectExternalStore(() => source), + (value) => { + expect(value()).toBe(1) + source.set(2) + }, + ) + fixture.detectChanges() + expect(fixture.componentInstance.value()).toBe(2) + source.set(3) + expect(fixture.componentInstance.value()).toBe(3) + }) + + it.each([false, true])( + 'reflects changes made by subscription setup (notifies: %s)', + (notifies) => { + const source = store(1) + const fixture = host(() => + injectExternalStore(() => ({ + getSnapshot: source.getSnapshot, + subscribe: (notify) => { + source.set(2) + if (notifies) notify() + return source.subscribe(notify) + }, + })), + ) + fixture.detectChanges() + expect(fixture.componentInstance.value()).toBe(2) + source.set(3) + expect(fixture.componentInstance.value()).toBe(3) + }, + ) + + it('preserves equal snapshots for consumers', () => { + const source = store(1) + const fixture = host(() => + injectExternalStore( + () => ({ + getSnapshot: () => ({ count: source.getSnapshot() }), + subscribe: source.subscribe, + }), + { equal: (a, b) => a.count === b.count }, + ), + ) + fixture.detectChanges() + const derive = vi.fn(() => fixture.componentInstance.value().count) + const derived = computed(derive) + expect(derived()).toBe(1) + source.set(1) + expect(derived()).toBe(1) + expect(derive).toHaveBeenCalledOnce() + source.set(2) + expect(derived()).toBe(2) + }) + + it('tracks snapshot dependencies without reconnecting for selectors or incidental reads', () => { + const source = store(0) + const multiplier = signal(10) + const incidental = signal(0) + const fixture = host(() => + injectExternalStore(() => ({ + getSnapshot: () => (source.getSnapshot() > 0 ? multiplier() : 0), + subscribe: (notify) => { + incidental() + return source.subscribe(notify) + }, + })), + ) + fixture.detectChanges() + const value = fixture.componentInstance.value + expect(value()).toBe(0) + source.set(1) + expect(value()).toBe(10) + multiplier.set(20) + incidental.set(1) + fixture.detectChanges() + expect(value()).toBe(20) + expect(source.subscribe).toHaveBeenCalledOnce() + }) + + it('follows the current source and releases the previous source', () => { + const first = store(1) + const second = store(10) + const requested = signal(first) + const fixture = host(() => injectExternalStore(() => requested())) + fixture.detectChanges() + const value = fixture.componentInstance.value + expect(value()).toBe(1) + requested.set(second) + expect(value()).toBe(10) + second.set(11) + fixture.detectChanges() + expect(value()).toBe(11) + expect(first.cleanup).toHaveBeenCalledOnce() + first.set(2) + expect(value()).toBe(11) + second.set(12) + expect(value()).toBe(12) + }) + + it('releases observation while paused and catches up on resume', () => { + const source = store(1) + const paused = signal(false) + const fixture = host(() => + injectExternalStore(() => ({ + getSnapshot: source.getSnapshot, + subscribe: paused() ? undefined : source.subscribe, + })), + ) + fixture.detectChanges() + paused.set(true) + fixture.detectChanges() + expect(source.cleanup).toHaveBeenCalledOnce() + source.set(2) + paused.set(false) + fixture.detectChanges() + expect(fixture.componentInstance.value()).toBe(2) + source.set(3) + expect(fixture.componentInstance.value()).toBe(3) + }) + + it('allows subscription setup and cleanup to read the result', () => { + const source = store(1) + const enabled = signal(true) + const seen: Array = [] + const fixture = host(() => { + const value = injectExternalStore(() => ({ + getSnapshot: source.getSnapshot, + subscribe: enabled() + ? (notify: () => void) => { + seen.push(value()) + const cleanup = source.subscribe(notify) + return () => { + seen.push(value()) + cleanup() + } + } + : undefined, + })) + return value + }) + fixture.detectChanges() + enabled.set(false) + fixture.detectChanges() + expect(seen).toEqual([1, 1]) + }) + + it('keeps snapshot errors separate from subscription errors', () => { + const source = store(1) + const fixture = host(() => + injectExternalStore(() => ({ + getSnapshot: source.getSnapshot, + subscribe: () => { + source.set(2) + throw new Error('subscribe failed') + }, + })), + ) + expect(() => fixture.detectChanges()).toThrow('subscribe failed') + expect(fixture.componentInstance.value()).toBe(2) + }) + + it('recovers from a snapshot error on the next store notification', () => { + const source = store(1) + const fixture = host(() => + injectExternalStore(() => ({ + getSnapshot: () => { + if (source.getSnapshot() === 2) throw new Error('snapshot failed') + return source.getSnapshot() + }, + subscribe: source.subscribe, + })), + ) + fixture.detectChanges() + source.set(2) + expect(() => fixture.componentInstance.value()).toThrow('snapshot failed') + source.set(3) + expect(fixture.componentInstance.value()).toBe(3) + expect(source.subscribe).toHaveBeenCalledOnce() + }) + + it.each([false, true])( + 'releases subscriptions on destruction (during setup: %s)', + (duringSetup) => { + const source = store(1) + const fixture = host(() => + injectExternalStore(() => ({ + getSnapshot: source.getSnapshot, + subscribe: (notify) => { + const cleanup = source.subscribe(notify) + if (duringSetup) fixture.destroy() + return cleanup + }, + })), + ) + fixture.detectChanges() + if (!duringSetup) fixture.destroy() + expect(source.cleanup).toHaveBeenCalledOnce() + }, + ) + + it('renders required inputs and changes made in ngOnInit', () => { + const source = store(1) + @Component({ template: '{{ value() }}' }) + class Example { + readonly source = input.required>() + readonly value = injectExternalStore(() => this.source()) + ngOnInit() { + expect(this.value()).toBe(1) + this.source().set(2) + } + } + const fixture = TestBed.createComponent(Example, { + bindings: [inputBinding('source', () => source)], + }) + fixture.detectChanges() + expect(fixture.nativeElement.textContent).toBe('2') + source.set(3) + fixture.detectChanges() + expect(fixture.nativeElement.textContent).toBe('3') + }) +}) diff --git a/packages/angular-query/src/utils/inject-external-store.ts b/packages/angular-query/src/utils/inject-external-store.ts new file mode 100644 index 00000000000..a7bc3aa5641 --- /dev/null +++ b/packages/angular-query/src/utils/inject-external-store.ts @@ -0,0 +1,88 @@ +import { + DestroyRef, + assertInInjectionContext, + computed, + effect, + inject, + signal, + untracked, +} from '@angular/core' +import { injectQueryZone } from './inject-query-zone' +import type { Signal, ValueEqualityFn } from '@angular/core' + +interface ExternalBinding { + /** Synchronous snapshot. Angular signals read here are tracked dependencies. */ + readonly getSnapshot: () => T + /** Omit to pause observation; changing eligibility requires a new descriptor. */ + readonly subscribe?: ((notify: () => void) => () => void) | undefined +} + +interface ExternalStoreOptions { + /** Snapshot equality, defaulting to Object.is. Does not control connection identity. */ + readonly equal?: ValueEqualityFn | undefined +} + +/** + * Creates a readonly Angular signal backed by a synchronous external store. + * + * Store access, subscription setup, and cleanup run outside NgZone so background + * timers do not hold Angular stability open. + * + * Reads evaluate snapshots without subscribing. An effect owns the subscription + * and invalidates the snapshot after setup, closing the gap between an early + * read and connection. The next read recomputes the snapshot; equality prevents + * unchanged values from propagating. Unread snapshots stay lazy. + * + * Notifications invalidate snapshots synchronously once connected. Snapshot-only + * dependencies do not reinstall the subscription. Subscription setup and cleanup + * may read the returned signal; factories and snapshot readers must not recurse. + * + * Only factory/snapshot errors are exposed on reads. Subscription and cleanup + * errors follow Angular's normal effect error handling; the helper does not store + * them or implement retries. Destruction stops observation without changing the + * cached snapshot. + */ +export function injectExternalStore( + binding: () => ExternalBinding, + options?: ExternalStoreOptions, +): Signal { + if (typeof ngDevMode === 'undefined' || ngDevMode) { + assertInInjectionContext(injectExternalStore) + } + const owner = inject(DestroyRef) + const outsideZone = injectQueryZone() + const revision = signal(0) + const requested = computed(() => outsideZone(binding)) + const invalidate = () => untracked(() => revision.update((n) => n + 1)) + + effect((onCleanup) => { + // The previous subscription's cleanup may have destroyed the owner. + if (owner.destroyed) return + const current = requested() + outsideZone(() => + untracked(() => { + try { + const unsubscribe = current.subscribe?.(invalidate) + if (unsubscribe) { + // subscribe() can trigger component/injector destruction before returning. + // Registering cleanup afterward misses that destruction. + if (owner.destroyed) unsubscribe() + else onCleanup(() => outsideZone(unsubscribe)) + } + } finally { + // Invalidate after subscribing so an early cached snapshot cannot miss + // changes before or during setup. Do not eagerly read the snapshot. + invalidate() + } + }), + ) + }) + + return computed( + () => { + revision() + return outsideZone(() => requested().getSnapshot()) + }, + options?.equal ? { equal: options.equal } : undefined, + ) +} diff --git a/packages/angular-query/src/utils/inject-pending-tasks-lifecycle.ts b/packages/angular-query/src/utils/inject-pending-tasks-lifecycle.ts new file mode 100644 index 00000000000..866d256d4f2 --- /dev/null +++ b/packages/angular-query/src/utils/inject-pending-tasks-lifecycle.ts @@ -0,0 +1,41 @@ +import { DestroyRef, NgZone, PendingTasks, inject } from '@angular/core' + +export interface QueryLifecycle { + readonly destroyed: boolean + setPending: (pending: boolean) => void +} + +/** Tracks pending work for the lifetime of the current injection context. */ +export function injectPendingTasksLifecycle(): QueryLifecycle { + const destroyRef = inject(DestroyRef) + const pendingTasks = inject(PendingTasks) + const ngZone = inject(NgZone) + let taskCleanup: (() => void) | undefined + + const lifecycle: QueryLifecycle = { + get destroyed() { + return destroyRef.destroyed + }, + setPending(pending) { + if (pending) { + if (!destroyRef.destroyed && !taskCleanup) { + taskCleanup = pendingTasks.add() + } + return + } + + const cleanup = taskCleanup + taskCleanup = undefined + // Enter NgZone while our task is still held to avoid transient stability + // before dependent queries are scheduled. + // In zoneless apps, NgZone.run simply invokes the cleanup. + if (cleanup) ngZone.run(cleanup) + }, + } + + destroyRef.onDestroy(() => { + lifecycle.setPending(false) + }) + + return lifecycle +} diff --git a/packages/angular-query/src/utils/inject-query-zone.ts b/packages/angular-query/src/utils/inject-query-zone.ts new file mode 100644 index 00000000000..1d14f7eb049 --- /dev/null +++ b/packages/angular-query/src/utils/inject-query-zone.ts @@ -0,0 +1,7 @@ +import { NgZone, inject } from '@angular/core' + +/** Keep Query's background timers out of Angular's stability tracking. */ +export function injectQueryZone() { + const ngZone = inject(NgZone) + return (fn: () => T): T => ngZone.runOutsideAngular(fn) +} diff --git a/packages/angular-query/src/utils/resource-types.ts b/packages/angular-query/src/utils/resource-types.ts new file mode 100644 index 00000000000..7ab266e929e --- /dev/null +++ b/packages/angular-query/src/utils/resource-types.ts @@ -0,0 +1,10 @@ +import type { ResourceStatus } from '@angular/core' + +// Angular 20 does not expose ResourceSnapshot. Remove this local type when the +// minimum supported Angular version provides it. +export type ResourceSnapshot = + | { readonly status: 'error'; readonly error: Error } + | { + readonly status: Exclude + readonly value: T + } diff --git a/packages/angular-query/src/utils/result-fields.ts b/packages/angular-query/src/utils/result-fields.ts new file mode 100644 index 00000000000..598ac07b4e7 --- /dev/null +++ b/packages/angular-query/src/utils/result-fields.ts @@ -0,0 +1,73 @@ +import type { + InfiniteQueryObserverResult, + MutationObserverResult, + QueryObserverResult, +} from '@tanstack/query-core' +import type { MethodKeys } from './signal-proxy' + +type Fields = { [K in Exclude>]: true } + +// Exhaustive maps keep the field surface aligned with query-core at compile time. +const queryFields = { + data: true, + dataUpdatedAt: true, + error: true, + errorUpdatedAt: true, + failureCount: true, + failureReason: true, + errorUpdateCount: true, + isError: true, + isFetched: true, + isFetchedAfterMount: true, + isFetching: true, + isLoading: true, + isPending: true, + isLoadingError: true, + isInitialLoading: true, + isPaused: true, + isPlaceholderData: true, + isRefetchError: true, + isRefetching: true, + isStale: true, + isSuccess: true, + isEnabled: true, + status: true, + fetchStatus: true, +} satisfies Fields + +const infiniteQueryFields = { + ...queryFields, + hasNextPage: true, + hasPreviousPage: true, + isFetchNextPageError: true, + isFetchingNextPage: true, + isFetchPreviousPageError: true, + isFetchingPreviousPage: true, +} satisfies Fields + +const mutationFields = { + context: true, + data: true, + error: true, + failureCount: true, + failureReason: true, + isPaused: true, + status: true, + variables: true, + submittedAt: true, + isError: true, + isIdle: true, + isPending: true, + isSuccess: true, +} satisfies Fields + +export const queryResultFields = /* @__PURE__ */ Object.keys( + queryFields, +) as Array +export const infiniteQueryResultFields = /* @__PURE__ */ Object.keys( + infiniteQueryFields, +) as Array + +export const mutationResultFields = /* @__PURE__ */ Object.keys( + mutationFields, +) as Array diff --git a/packages/angular-query/src/utils/signal-proxy.ts b/packages/angular-query/src/utils/signal-proxy.ts new file mode 100644 index 00000000000..cc6305bc42d --- /dev/null +++ b/packages/angular-query/src/utils/signal-proxy.ts @@ -0,0 +1,29 @@ +import { computed } from '@angular/core' +import type { Signal } from '@angular/core' + +export type MethodKeys = { + [K in keyof T]: T[K] extends (...args: Array) => any ? K : never +}[keyof T] + +export type MapToSignals = never> = { + [K in keyof T]: K extends TExcludeFields ? T[K] : Signal +} + +/** + * Maps known result fields to lazy computed signals on an ordinary object. + * Creating or enumerating the fields never evaluates the source. Imperative + * methods are defined by each adapter, outside this mapping. + * @param inputSignal - The source snapshot. + * @param fields - The fields exposed as signals. + * @returns An object containing one stable signal per field. + */ +export function signalProxy( + inputSignal: Signal, + fields: ReadonlyArray, +): { [P in TField]: Signal } { + const result = {} as { [P in TField]: Signal } + for (const field of fields) { + result[field] = computed(() => inputSignal()[field]) + } + return result +} diff --git a/packages/angular-query/test-setup.ts b/packages/angular-query/test-setup.ts new file mode 100644 index 00000000000..eb69f3f05a9 --- /dev/null +++ b/packages/angular-query/test-setup.ts @@ -0,0 +1,9 @@ +import '@testing-library/jest-dom/vitest' +import '@angular/compiler' +import { getTestBed } from '@angular/core/testing' +import { + BrowserTestingModule, + platformBrowserTesting, +} from '@angular/platform-browser/testing' + +getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting()) diff --git a/packages/angular-query/test-setup.zoneful.ts b/packages/angular-query/test-setup.zoneful.ts new file mode 100644 index 00000000000..4f24c5e4cf7 --- /dev/null +++ b/packages/angular-query/test-setup.zoneful.ts @@ -0,0 +1,13 @@ +import 'zone.js' +import 'zone.js/testing' +import '@testing-library/jest-dom/vitest' +import '@angular/compiler' +import { getTestBed } from '@angular/core/testing' +import { + BrowserTestingModule, + platformBrowserTesting, +} from '@angular/platform-browser/testing' + +process.env.ANGULAR_QUERY_ZONEFUL = 'true' + +getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting()) diff --git a/packages/angular-query-experimental/tsconfig.json b/packages/angular-query/tsconfig.json similarity index 78% rename from packages/angular-query-experimental/tsconfig.json rename to packages/angular-query/tsconfig.json index 3699e26689d..46b74afcf24 100644 --- a/packages/angular-query-experimental/tsconfig.json +++ b/packages/angular-query/tsconfig.json @@ -16,11 +16,13 @@ }, "include": [ "src", + "schematics", + "schematics-build", "scripts", "test-setup.ts", - "*.config.ts", - "*.config.js", + "*.config.*", "package.json" ], - "references": [{ "path": "../query-devtools" }] + "exclude": ["src/**/*.tmp.test.ts"], + "references": [{ "path": "../query-core" }] } diff --git a/packages/angular-query-experimental/tsconfig.prod.json b/packages/angular-query/tsconfig.prod.json similarity index 100% rename from packages/angular-query-experimental/tsconfig.prod.json rename to packages/angular-query/tsconfig.prod.json diff --git a/packages/angular-query/tsconfig.schematics.json b/packages/angular-query/tsconfig.schematics.json new file mode 100644 index 00000000000..470c02914cd --- /dev/null +++ b/packages/angular-query/tsconfig.schematics.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "declaration": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "lib": ["ES2022"], + "module": "CommonJS", + "moduleResolution": "Node", + "ignoreDeprecations": "6.0", + "noEmitOnError": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "dist/schematics", + "rootDir": "schematics", + "skipLibCheck": true, + "strict": true, + "target": "ES2022", + "types": ["node"] + }, + "include": ["schematics/**/*.ts"] +} diff --git a/packages/angular-query/tsconfig.spec.json b/packages/angular-query/tsconfig.spec.json new file mode 100644 index 00000000000..c70b776b257 --- /dev/null +++ b/packages/angular-query/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "types": ["vitest/globals", "node"], + "noEmit": false, + "emitDeclarationOnly": false, + "declaration": false, + "declarationMap": false, + "composite": false, + "target": "ES2022" + }, + "files": ["test-setup.ts"], + "include": ["src/**/*.test.ts", "../query-test-utils/src/**/*.ts"], + "exclude": ["src/**/*.test-d.ts", "src/**/*.tmp.test.ts"] +} diff --git a/packages/angular-query-experimental/vite.config.ts b/packages/angular-query/vite.config.ts similarity index 69% rename from packages/angular-query-experimental/vite.config.ts rename to packages/angular-query/vite.config.ts index d5337c94ea6..5cfbcd37b9f 100644 --- a/packages/angular-query-experimental/vite.config.ts +++ b/packages/angular-query/vite.config.ts @@ -1,8 +1,7 @@ -import { defineConfig, mergeConfig } from 'vitest/config' +import { defineConfig, mergeConfig } from 'vite' import { externalizeDeps } from 'vite-plugin-externalize-deps' import tsconfigPaths from 'vite-tsconfig-paths' import dts from 'vite-plugin-dts' -import packageJson from './package.json' import type { Options } from '@tanstack/vite-config' function ensureImportFileExtension({ @@ -14,14 +13,20 @@ function ensureImportFileExtension({ }) { // replace e.g. `import { foo } from './foo'` with `import { foo } from './foo.js'` content = content.replace( - /(im|ex)port\s[\w{}/*\s,]+from\s['"](?:\.\.?\/)+?[^.'"]+(?=['"];?)/gm, - `$&.${extension}`, + /(im|ex)port\s[\w{}/*\s,]+from\s['"](?:\.\.?\/)+?[^'"]+(?=['"];?)/gm, + (specifier) => + /\.(?:[cm]?js|json)$/.test(specifier) + ? specifier + : `${specifier}.${extension}`, ) // replace e.g. `import('./foo')` with `import('./foo.js')` content = content.replace( - /import\(['"](?:\.\.?\/)+?[^.'"]+(?=['"];?)/gm, - `$&.${extension}`, + /import\(['"](?:\.\.?\/)+?[^'"]+(?=['"];?)/gm, + (specifier) => + /\.(?:[cm]?js|json)$/.test(specifier) + ? specifier + : `${specifier}.${extension}`, ) return content } @@ -31,29 +36,6 @@ const config = defineConfig({ resolve: { conditions: ['@tanstack/custom-condition'], }, - environments: { - ssr: { - resolve: { - conditions: ['@tanstack/custom-condition'], - }, - }, - }, - test: { - name: packageJson.name, - dir: './src', - watch: false, - environment: 'jsdom', - setupFiles: ['test-setup.ts'], - coverage: { - enabled: !!process.env.CI, - provider: 'istanbul', - include: ['src/**/*'], - exclude: ['src/__tests__/**'], - }, - typecheck: { enabled: true }, - globals: true, - restoreMocks: true, - }, }) // copy from @tanstack/config/vite with changes: @@ -116,15 +98,8 @@ export default mergeConfig( config, tanstackViteConfig({ cjs: false, - entry: [ - './src/index.ts', - './src/inject-queries-experimental/index.ts', - './src/devtools-panel/index.ts', - './src/devtools-panel/stub.ts', - './src/devtools/index.ts', - './src/devtools/stub.ts', - ], - exclude: ['src/__tests__'], + entry: ['./src/index.ts', './src/internal.ts'], + exclude: ['src/**/__tests__/**', 'src/**/__test__/**'], srcDir: './src', tsconfigPath: 'tsconfig.prod.json', }), diff --git a/packages/angular-query/vitest.config.ts b/packages/angular-query/vitest.config.ts new file mode 100644 index 00000000000..da0e57d9dd9 --- /dev/null +++ b/packages/angular-query/vitest.config.ts @@ -0,0 +1,57 @@ +import { defineConfig } from 'vitest/config' +import angular from '@analogjs/vite-plugin-angular' +import packageJson from './package.json' with { type: 'json' } + +export default defineConfig({ + // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660 + resolve: { + conditions: ['@tanstack/custom-condition'], + }, + environments: { + ssr: { + resolve: { + conditions: ['@tanstack/custom-condition'], + }, + }, + }, + esbuild: { + target: 'es2022', + }, + plugins: [ + angular({ + tsconfig: './tsconfig.spec.json', + // Vitest sets VITEST; Analog defaults jit: true, which skips ngtsc transforms for + // signal inputs so inputBinding() fails (NG0315). jit: false needs compiler-cli on + // the same TypeScript 5.9 version as the plugin to avoid mixed compiler ASTs. + jit: false, + }), + ], + test: { + name: packageJson.name, + dir: './src', + watch: false, + environment: 'jsdom', + setupFiles: ['./test-setup.ts'], + coverage: { + enabled: !!process.env.CI, + provider: 'istanbul', + include: ['src/**/*'], + exclude: ['src/__tests__/**'], + }, + include: ['**/*.{test,spec}.{ts,mts,cts,tsx,js,mjs,cjs,jsx}'], + // The focused Zone.js project opts this file back in. The default project + // must not load provideZoneChangeDetection without the Zone.js setup file. + exclude: [ + '**/zoneful-integration.test.ts', + '**/*.zoneful.test.ts', + '**/*.tmp.test.ts', + ], + typecheck: { + enabled: true, + include: ['**/*.test-d.ts'], + exclude: ['**/*.tmp.test.ts'], + }, + globals: true, + restoreMocks: true, + }, +}) diff --git a/packages/angular-query/vitest.schematics.config.ts b/packages/angular-query/vitest.schematics.config.ts new file mode 100644 index 00000000000..b1f64767770 --- /dev/null +++ b/packages/angular-query/vitest.schematics.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'vitest/config' +import packageJson from './package.json' with { type: 'json' } + +export default defineConfig({ + test: { + name: `${packageJson.name}:schematics`, + environment: 'node', + include: ['./schematics-build/**/*.test.ts'], + watch: false, + }, +}) diff --git a/packages/angular-query/vitest.zoneful.config.ts b/packages/angular-query/vitest.zoneful.config.ts new file mode 100644 index 00000000000..ba55e0e73d5 --- /dev/null +++ b/packages/angular-query/vitest.zoneful.config.ts @@ -0,0 +1,34 @@ +import { defineConfig, mergeConfig } from 'vitest/config' +import baseConfig from './vitest.config' + +/** + * Runs the Angular tests with Zone.js enabled. Tests use the change-detection + * provider from test-utils, which selects provideZoneChangeDetection here and + * provideZonelessChangeDetection in the default runner. + */ +const config = mergeConfig( + baseConfig, + defineConfig({ + test: { + setupFiles: ['./test-setup.zoneful.ts'], + }, + }), +) + +// The base project excludes the Zone.js-only integration file so an ordinary +// run remains genuinely zoneless. The Zone.js project explicitly opts it in. +if (config.test) { + // Replace, rather than merge with, the base setup so Zone.js is installed + // before Angular initializes its browser testing environment. + config.test.setupFiles = ['./test-setup.zoneful.ts'] + config.test.include = [ + '**/zoneful-integration.test.ts', + '**/pending-tasks.test.ts', + '**/pending-tasks-ssr.zoneful.test.ts', + '**/upstream-issues.test.ts', + '**/inject-external-store.test.ts', + ] + config.test.exclude = [] +} + +export default config diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b08f4ef9a7a..0052ab846c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,7 @@ settings: excludeLinksFromLockfile: false overrides: + '@inquirer/external-editor': 3.0.5 chokidar: 5.0.0 '@types/react': ^19.2.7 '@types/react-dom': ^19.2.3 @@ -22,6 +23,7 @@ overrides: '@typescript-eslint/visitor-keys': 8.58.1 typescript-eslint: 8.58.1 vite: ^6.4.1 + '@angular/build@22.1.8>vite': 7.1.11 esbuild: ^0.27.2 importers: @@ -54,7 +56,7 @@ importers: version: 0.3.1(typescript@6.0.3) '@tanstack/vite-config': specifier: 0.4.3 - version: 0.4.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 0.4.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@testing-library/jest-dom': specifier: ^6.8.0 version: 6.9.1 @@ -69,10 +71,10 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitest/coverage-istanbul': specifier: 4.0.6 - version: 4.0.6(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 4.0.6(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) '@vitest/eslint-plugin': specifier: ^1.4.0 - version: 1.6.14(@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 1.6.14(@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) eslint: specifier: ^9.36.0 version: 9.39.4(jiti@2.7.0) @@ -141,28 +143,31 @@ importers: version: typescript@7.0.2 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) vitest: specifier: ^4.0.18 - version: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) examples/angular/auto-refetching: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools rxjs: specifier: ^7.8.2 version: 7.8.2 @@ -170,39 +175,42 @@ importers: specifier: ^2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(52d17f587f491aa5bd2e2175a98e7579) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 examples/angular/basic: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools rxjs: specifier: ^7.8.2 version: 7.8.2 @@ -210,44 +218,47 @@ importers: specifier: ^2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 examples/angular/basic-persister: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools '@tanstack/angular-query-persist-client': - specifier: ^5.103.2 + specifier: workspace:* version: link:../../../packages/angular-query-persist-client '@tanstack/query-async-storage-persister': - specifier: ^5.103.2 + specifier: ^5.100.14 version: link:../../../packages/query-async-storage-persister rxjs: specifier: ^7.8.2 @@ -256,42 +267,45 @@ importers: specifier: ^2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 examples/angular/devtools-panel: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) '@angular/router': - specifier: ^20.0.0 - version: 20.3.18(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools rxjs: specifier: ^7.8.2 version: 7.8.2 @@ -299,39 +313,128 @@ importers: specifier: ^2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 + + examples/angular/dynamic-devtools: + dependencies: + '@angular/common': + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/compiler': + specifier: ^22.0.0 + version: 22.1.6 + '@angular/core': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools + rxjs: + specifier: ^7.8.2 + version: 7.8.2 + tslib: + specifier: ^2.8.1 + version: 2.8.1 + zone.js: + specifier: 0.16.1 + version: 0.16.1 + devDependencies: + '@angular/build': + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) + '@angular/cli': + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) + '@angular/compiler-cli': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) + typescript: + specifier: 6.0.3 + version: 6.0.3 + + examples/angular/dynamic-queries: + dependencies: + '@angular/common': + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/compiler': + specifier: ^22.0.0 + version: 22.1.6 + '@angular/core': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools + rxjs: + specifier: ^7.8.2 + version: 7.8.2 + tslib: + specifier: ^2.8.1 + version: 2.8.1 + zone.js: + specifier: 0.16.1 + version: 0.16.1 + devDependencies: + '@angular/build': + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) + '@angular/cli': + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) + '@angular/compiler-cli': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) + typescript: + specifier: 6.0.3 + version: 6.0.3 examples/angular/infinite-query-with-max-pages: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools rxjs: specifier: ^7.8.2 version: 7.8.2 @@ -339,42 +442,45 @@ importers: specifier: ^2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 examples/angular/optimistic-updates: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/forms': - specifier: ^20.0.0 - version: 20.3.18(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools rxjs: specifier: ^7.8.2 version: 7.8.2 @@ -382,39 +488,42 @@ importers: specifier: ^2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 examples/angular/pagination: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools rxjs: specifier: ^7.8.2 version: 7.8.2 @@ -422,42 +531,45 @@ importers: specifier: ^2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 examples/angular/query-options-from-a-service: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) '@angular/router': - specifier: ^20.0.0 - version: 20.3.18(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools rxjs: specifier: ^7.8.2 version: 7.8.2 @@ -465,42 +577,45 @@ importers: specifier: ^2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 examples/angular/router: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) '@angular/router': - specifier: ^20.0.0 - version: 20.3.18(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools rxjs: specifier: ^7.8.2 version: 7.8.2 @@ -508,42 +623,45 @@ importers: specifier: ^2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 examples/angular/rxjs: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/forms': - specifier: ^20.0.0 - version: 20.3.18(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools rxjs: specifier: ^7.8.2 version: 7.8.2 @@ -551,39 +669,42 @@ importers: specifier: ^2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 examples/angular/simple: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools rxjs: specifier: ^7.8.2 version: 7.8.2 @@ -591,21 +712,183 @@ importers: specifier: ^2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 + + examples/angular/ssr: + dependencies: + '@angular/common': + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/compiler': + specifier: ^22.0.0 + version: 22.1.6 + '@angular/core': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@angular/platform-server': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/compiler@22.1.6)(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@angular/ssr': + specifier: ^22.0.0 + version: 22.1.8(caf12b5b30d21bb6295944d46eee472d) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools + express: + specifier: ^5.1.0 + version: 5.2.1 + rxjs: + specifier: ^7.8.2 + version: 7.8.2 + tslib: + specifier: ^2.8.1 + version: 2.8.1 + zone.js: + specifier: 0.16.1 + version: 0.16.1 + devDependencies: + '@angular/build': + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) + '@angular/cli': + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) + '@angular/compiler-cli': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) + '@types/express': + specifier: ^5.0.1 + version: 5.0.6 + typescript: + specifier: 6.0.3 + version: 6.0.3 + + examples/angular/ssr-persist: + dependencies: + '@angular/common': + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/compiler': + specifier: ^22.0.0 + version: 22.1.6 + '@angular/core': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@angular/platform-server': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/compiler@22.1.6)(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@angular/ssr': + specifier: ^22.0.0 + version: 22.1.8(caf12b5b30d21bb6295944d46eee472d) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools + '@tanstack/angular-query-persist-client': + specifier: workspace:* + version: link:../../../packages/angular-query-persist-client + '@tanstack/query-async-storage-persister': + specifier: workspace:* + version: link:../../../packages/query-async-storage-persister + express: + specifier: ^5.1.0 + version: 5.2.1 + rxjs: + specifier: ^7.8.2 + version: 7.8.2 + tslib: + specifier: ^2.8.1 + version: 2.8.1 + zone.js: + specifier: 0.16.1 + version: 0.16.1 + devDependencies: + '@angular/build': + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) + '@angular/cli': + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) + '@angular/compiler-cli': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) + '@types/express': + specifier: ^5.0.1 + version: 5.0.6 + typescript: + specifier: 6.0.3 + version: 6.0.3 + + examples/angular/to-resource-signal-forms: + dependencies: + '@angular/common': + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/compiler': + specifier: ^22.0.0 + version: 22.1.6 + '@angular/core': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/forms': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@angular/platform-browser': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../../packages/angular-query-devtools + rxjs: + specifier: ^7.8.2 + version: 7.8.2 + tslib: + specifier: ^2.8.1 + version: 2.8.1 + zone.js: + specifier: 0.16.1 + version: 0.16.1 + devDependencies: + '@angular/build': + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) + '@angular/cli': + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) + '@angular/compiler-cli': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) + typescript: + specifier: 6.0.3 + version: 6.0.3 examples/lit/basic: dependencies: @@ -624,7 +907,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/lit/pagination: dependencies: @@ -643,7 +926,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/lit/ssr: dependencies: @@ -671,7 +954,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/preact/simple: dependencies: @@ -684,7 +967,7 @@ importers: devDependencies: '@preact/preset-vite': specifier: ^2.10.2 - version: 2.10.5(@babel/core@7.29.7)(preact@10.29.0)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.10.5(@babel/core@7.29.7)(preact@10.29.0)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) eslint: specifier: ^9.36.0 version: 9.39.4(jiti@2.7.0) @@ -696,7 +979,7 @@ importers: version: 5.9.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/algolia: dependencies: @@ -727,13 +1010,13 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/auto-refetching: dependencies: @@ -745,7 +1028,7 @@ importers: version: link:../../../packages/react-query-devtools next: specifier: ^16.0.7 - version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: specifier: ^19.2.1 version: 19.2.4 @@ -795,13 +1078,13 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/basic-graphql-request: dependencies: @@ -826,10 +1109,10 @@ importers: devDependencies: '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/batching: dependencies: @@ -860,13 +1143,13 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/chat: dependencies: @@ -885,10 +1168,10 @@ importers: devDependencies: '@tailwindcss/vite': specifier: ^4.0.14 - version: 4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) tailwindcss: specifier: ^4.0.14 version: 4.2.2 @@ -897,7 +1180,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/default-query-function: dependencies: @@ -916,13 +1199,13 @@ importers: devDependencies: '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/devtools-panel: dependencies: @@ -941,13 +1224,13 @@ importers: devDependencies: '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/eslint-legacy: dependencies: @@ -981,13 +1264,13 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/eslint-plugin-demo: dependencies: @@ -1021,7 +1304,7 @@ importers: version: link:../../../packages/react-query-devtools next: specifier: ^16.0.7 - version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: specifier: ^19.2.1 version: 19.2.4 @@ -1049,7 +1332,7 @@ importers: version: link:../../../packages/react-query-devtools next: specifier: ^16.0.7 - version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: specifier: ^19.2.1 version: 19.2.4 @@ -1080,7 +1363,7 @@ importers: version: link:../../../packages/react-query-devtools next: specifier: ^16.0.7 - version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: specifier: ^19.2.1 version: 19.2.4 @@ -1108,7 +1391,7 @@ importers: version: link:../../../packages/react-query-devtools next: specifier: ^16.0.7 - version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: specifier: ^19.2.1 version: 19.2.4 @@ -1139,7 +1422,7 @@ importers: version: link:../../../packages/react-query-devtools next: specifier: ^16.0.7 - version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: specifier: ^19.2.1 version: 19.2.4 @@ -1170,7 +1453,7 @@ importers: version: link:../../../packages/react-query-next-experimental next: specifier: ^16.0.7 - version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: specifier: ^19.2.1 version: 19.2.4 @@ -1220,13 +1503,13 @@ importers: devDependencies: '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/pagination: dependencies: @@ -1238,7 +1521,7 @@ importers: version: link:../../../packages/react-query-devtools next: specifier: ^16.0.7 - version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: specifier: ^19.2.1 version: 19.2.4 @@ -1273,13 +1556,13 @@ importers: devDependencies: '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/prefetching: dependencies: @@ -1291,7 +1574,7 @@ importers: version: link:../../../packages/react-query-devtools next: specifier: ^16.0.7 - version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: specifier: ^19.2.1 version: 19.2.4 @@ -1414,13 +1697,13 @@ importers: version: 1.2.3 '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/rick-morty: dependencies: @@ -1445,10 +1728,10 @@ importers: devDependencies: '@tailwindcss/vite': specifier: ^4.1.13 - version: 4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) tailwindcss: specifier: ^4.1.13 version: 4.2.2 @@ -1457,7 +1740,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/shadow-dom: dependencies: @@ -1482,13 +1765,13 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/simple: dependencies: @@ -1507,13 +1790,13 @@ importers: devDependencies: '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/star-wars: dependencies: @@ -1538,10 +1821,10 @@ importers: devDependencies: '@tailwindcss/vite': specifier: ^4.1.13 - version: 4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) tailwindcss: specifier: ^4.1.13 version: 4.2.2 @@ -1550,7 +1833,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/react/suspense: dependencies: @@ -1575,13 +1858,13 @@ importers: devDependencies: '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/solid/astro: dependencies: @@ -1590,16 +1873,16 @@ importers: version: 0.9.8(prettier@3.8.1)(typescript@5.8.3) '@astrojs/node': specifier: ^9.1.3 - version: 9.5.5(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0)) + version: 9.5.5(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0)) '@astrojs/solid-js': specifier: ^5.0.7 - version: 5.1.3(@testing-library/jest-dom@6.9.1)(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(solid-js@1.9.12)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 5.1.3(@testing-library/jest-dom@6.9.1)(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(solid-js@1.9.12)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) '@astrojs/tailwind': specifier: ^6.0.2 - version: 6.0.2(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0))(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.9.0)) + version: 6.0.2(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0))(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.9.0)) '@astrojs/vercel': specifier: ^8.1.3 - version: 8.2.11(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0))(next@16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0))(react@19.2.4)(rollup@4.60.1)(svelte@5.55.1)(vue@3.5.31(typescript@5.8.3)) + version: 8.2.11(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0))(next@16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0))(react@19.2.4)(rollup@4.60.1)(svelte@5.55.1)(vue@3.5.31(typescript@5.8.3)) '@tanstack/solid-query': specifier: ^5.103.2 version: link:../../../packages/solid-query @@ -1608,7 +1891,7 @@ importers: version: link:../../../packages/solid-query-devtools astro: specifier: ^5.5.6 - version: 5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0) + version: 5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0) solid-js: specifier: ^1.9.7 version: 1.9.12 @@ -1636,10 +1919,10 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) examples/solid/basic-graphql-request: dependencies: @@ -1664,10 +1947,10 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) examples/solid/default-query-function: dependencies: @@ -1686,10 +1969,10 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) examples/solid/offline: dependencies: @@ -1717,10 +2000,10 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) examples/solid/simple: dependencies: @@ -1742,10 +2025,10 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) examples/solid/solid-start-streaming: dependencies: @@ -1757,7 +2040,7 @@ importers: version: 0.15.4(solid-js@1.9.12) '@solidjs/start': specifier: ^1.1.3 - version: 1.3.2(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.3.2(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@tanstack/solid-query': specifier: ^5.103.2 version: link:../../../packages/solid-query @@ -1769,7 +2052,7 @@ importers: version: 1.9.12 vinxi: specifier: ^0.5.3 - version: 0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0) + version: 0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0) examples/svelte/auto-refetching: dependencies: @@ -1782,13 +2065,13 @@ importers: devDependencies: '@sveltejs/adapter-auto': specifier: ^6.1.0 - version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) '@sveltejs/kit': specifier: ^2.57.1 - version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) svelte: specifier: ^5.39.3 version: 5.55.1 @@ -1800,7 +2083,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/svelte/basic: dependencies: @@ -1819,13 +2102,13 @@ importers: devDependencies: '@sveltejs/adapter-auto': specifier: ^6.1.0 - version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) '@sveltejs/kit': specifier: ^2.57.1 - version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) svelte: specifier: ^5.39.3 version: 5.55.1 @@ -1837,7 +2120,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/svelte/load-more-infinite-scroll: dependencies: @@ -1850,13 +2133,13 @@ importers: devDependencies: '@sveltejs/adapter-auto': specifier: ^6.1.0 - version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) '@sveltejs/kit': specifier: ^2.57.1 - version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) svelte: specifier: ^5.39.3 version: 5.55.1 @@ -1868,7 +2151,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/svelte/optimistic-updates: dependencies: @@ -1881,13 +2164,13 @@ importers: devDependencies: '@sveltejs/adapter-auto': specifier: ^6.1.0 - version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) '@sveltejs/kit': specifier: ^2.57.1 - version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) svelte: specifier: ^5.39.3 version: 5.55.1 @@ -1899,7 +2182,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/svelte/playground: dependencies: @@ -1912,13 +2195,13 @@ importers: devDependencies: '@sveltejs/adapter-auto': specifier: ^6.1.0 - version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) '@sveltejs/kit': specifier: ^2.57.1 - version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) svelte: specifier: ^5.39.3 version: 5.55.1 @@ -1930,7 +2213,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/svelte/simple: dependencies: @@ -1943,7 +2226,7 @@ importers: devDependencies: '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@tsconfig/svelte': specifier: ^5.0.4 version: 5.0.8 @@ -1958,7 +2241,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/svelte/ssr: dependencies: @@ -1971,13 +2254,13 @@ importers: devDependencies: '@sveltejs/adapter-auto': specifier: ^6.1.0 - version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) '@sveltejs/kit': specifier: ^2.57.1 - version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) svelte: specifier: ^5.39.3 version: 5.55.1 @@ -1989,7 +2272,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/svelte/star-wars: dependencies: @@ -2002,16 +2285,16 @@ importers: devDependencies: '@sveltejs/adapter-auto': specifier: ^6.1.0 - version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) '@sveltejs/kit': specifier: ^2.57.1 - version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@tailwindcss/vite': specifier: ^4.1.13 - version: 4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) svelte: specifier: ^5.39.3 version: 5.55.1 @@ -2026,7 +2309,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/vue/basic: dependencies: @@ -2042,13 +2325,13 @@ importers: devDependencies: '@vitejs/plugin-vue': specifier: ^5.2.1 - version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) + version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/vue/dependent-queries: dependencies: @@ -2061,13 +2344,13 @@ importers: devDependencies: '@vitejs/plugin-vue': specifier: ^5.2.1 - version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) + version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/vue/persister: dependencies: @@ -2092,13 +2375,13 @@ importers: devDependencies: '@vitejs/plugin-vue': specifier: ^5.2.1 - version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) + version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) examples/vue/simple: dependencies: @@ -2114,37 +2397,40 @@ importers: devDependencies: '@vitejs/plugin-vue': specifier: ^5.2.1 - version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) + version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) integrations/angular-cli-20: dependencies: '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/forms': - specifier: ^20.0.0 - version: 20.3.18(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) '@angular/router': - specifier: ^20.0.0 - version: 20.3.18(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) - '@tanstack/angular-query-experimental': - specifier: ^5.103.2 - version: link:../../packages/angular-query-experimental + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../../packages/angular-query + '@tanstack/angular-query-devtools': + specifier: workspace:* + version: link:../../packages/angular-query-devtools rxjs: specifier: ~7.8.0 version: 7.8.2 @@ -2152,21 +2438,21 @@ importers: specifier: ^2.3.0 version: 2.8.1 zone.js: - specifier: ~0.15.0 - version: 0.15.0 + specifier: ~0.16.0 + version: 0.16.1 devDependencies: '@angular/build': - specifier: ^20.0.0 - version: 20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0) + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/cli': - specifier: ^20.0.0 - version: 20.3.22(@types/node@22.19.15)(chokidar@5.0.0) + specifier: ^22.0.0 + version: 22.1.8(@types/node@22.19.15)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) typescript: - specifier: ~5.8.2 - version: 5.8.3 + specifier: 6.0.3 + version: 6.0.3 integrations/lit-vite: dependencies: @@ -2181,7 +2467,7 @@ importers: version: 3.3.2 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) devDependencies: typescript: specifier: 5.8.3 @@ -2197,7 +2483,7 @@ importers: version: link:../../packages/react-query-devtools next: specifier: ^14.2.33 - version: 14.2.35(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.90.0) + version: 14.2.35(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.101.0) react: specifier: ^18.2.0 version: 18.3.1 @@ -2225,7 +2511,7 @@ importers: version: link:../../packages/react-query-devtools next: specifier: ^15.4.8 - version: 15.5.14(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 15.5.14(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: specifier: ^19.2.1 version: 19.2.4 @@ -2256,7 +2542,7 @@ importers: version: link:../../packages/react-query-devtools next: specifier: ^16.0.7 - version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: specifier: ^19.2.1 version: 19.2.4 @@ -2294,7 +2580,7 @@ importers: version: link:../../packages/react-query-devtools '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) react: specifier: ^19.0.0 version: 19.2.4 @@ -2303,7 +2589,7 @@ importers: version: 19.2.4(react@19.2.4) vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) integrations/react-webpack-4: dependencies: @@ -2395,16 +2681,16 @@ importers: version: 1.9.12 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) integrations/svelte-vite: devDependencies: '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@tanstack/svelte-query': specifier: workspace:* version: link:../../packages/svelte-query @@ -2416,7 +2702,7 @@ importers: version: 5.55.1 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) integrations/vue-declaration-emit: dependencies: @@ -2442,60 +2728,145 @@ importers: devDependencies: '@vitejs/plugin-vue': specifier: ^5.2.1 - version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) + version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) typescript: specifier: 5.8.3 version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) vue-tsc: specifier: ^2.2.8 version: 2.2.12(typescript@5.8.3) - packages/angular-query-experimental: + packages/angular-query: dependencies: '@tanstack/query-core': specifier: workspace:* version: link:../query-core devDependencies: + '@analogjs/vite-plugin-angular': + specifier: ^2.3.1 + version: 2.5.2(@angular/build@22.1.8(4affaef227d0997be37379ba361cd6fd))(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@angular-devkit/schematics': + specifier: ^22.0.0 + version: 22.1.8(chokidar@5.0.0) + '@angular/build': + specifier: ^22.0.0 + version: 22.1.8(4affaef227d0997be37379ba361cd6fd) '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 + '@angular/compiler-cli': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@angular/platform-server': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/compiler@22.1.6)(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@angular/router': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@schematics/angular': + specifier: ^22.0.0 + version: 22.1.8(chokidar@5.0.0) '@tanstack/query-test-utils': specifier: workspace:* version: link:../query-test-utils '@testing-library/angular': - specifier: ^18.0.0 - version: 18.1.1(3436010aec00f8e828978cdcb451dc36) + specifier: ^18.1.1 + version: 18.1.1(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(@angular/router@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2))(@testing-library/dom@10.4.1) npm-run-all2: specifier: ^5.0.0 version: 5.0.2 rxjs: specifier: ^7.8.2 version: 7.8.2 + typescript: + specifier: 6.0.3 + version: 6.0.3 vite-plugin-dts: specifier: 4.2.3 - version: 4.2.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.2.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) vite-plugin-externalize-deps: specifier: ^0.9.0 - version: 0.9.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 0.9.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) - optionalDependencies: + version: 5.1.4(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + zone.js: + specifier: ^0.16.0 + version: 0.16.1 + publishDirectory: dist + + packages/angular-query-devtools: + dependencies: + '@tanstack/query-core': + specifier: workspace:* + version: link:../query-core '@tanstack/query-devtools': specifier: workspace:* version: link:../query-devtools + devDependencies: + '@analogjs/vite-plugin-angular': + specifier: ^2.3.1 + version: 2.5.2(@angular/build@22.1.8(e62ab7c722b8b89e816de2e21b02397f))(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@angular/build': + specifier: ^22.0.0 + version: 22.1.8(e62ab7c722b8b89e816de2e21b02397f) + '@angular/common': + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/compiler': + specifier: ^22.0.0 + version: 22.1.6 + '@angular/compiler-cli': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(typescript@5.9.3) + '@angular/core': + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@tanstack/angular-query': + specifier: workspace:* + version: link:../angular-query + '@testing-library/jest-dom': + specifier: ^6.8.0 + version: 6.9.1 + npm-run-all2: + specifier: ^5.0.0 + version: 5.0.2 + rxjs: + specifier: ^7.8.2 + version: 7.8.2 + typescript: + specifier: 5.9.3 + version: 5.9.3 + vite-plugin-dts: + specifier: 4.2.3 + version: 4.2.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite-plugin-externalize-deps: + specifier: ^0.9.0 + version: 0.9.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vitest: + specifier: ^4.0.18 + version: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + zone.js: + specifier: ^0.16.0 + version: 0.16.1 publishDirectory: dist packages/angular-query-persist-client: @@ -2504,30 +2875,30 @@ importers: specifier: workspace:* version: link:../query-persist-client-core devDependencies: - '@angular/animations': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) '@angular/common': - specifier: ^20.0.0 - version: 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: ^22.0.0 + version: 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^20.0.0 - version: 20.3.18 + specifier: ^22.0.0 + version: 22.1.6 '@angular/core': - specifier: ^20.0.0 - version: 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + specifier: ^22.0.0 + version: 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/platform-browser': - specifier: ^20.0.0 - version: 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - '@tanstack/angular-query-experimental': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@angular/router': + specifier: ^22.0.0 + version: 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@tanstack/angular-query': specifier: workspace:* - version: link:../angular-query-experimental + version: link:../angular-query '@tanstack/query-test-utils': specifier: workspace:* version: link:../query-test-utils '@testing-library/angular': - specifier: ^18.0.0 - version: 18.1.1(3436010aec00f8e828978cdcb451dc36) + specifier: ^18.1.1 + version: 18.1.1(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(@angular/router@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2))(@testing-library/dom@10.4.1) '@testing-library/dom': specifier: ^10.4.0 version: 10.4.1 @@ -2537,6 +2908,12 @@ importers: npm-run-all2: specifier: ^5.0.0 version: 5.0.2 + typescript: + specifier: 5.9.3 + version: 5.9.3 + zone.js: + specifier: ^0.16.0 + version: 0.16.1 packages/eslint-plugin-query: dependencies: @@ -2596,7 +2973,7 @@ importers: devDependencies: '@preact/preset-vite': specifier: ^2.10.2 - version: 2.10.5(@babel/core@7.29.7)(preact@10.29.0)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.10.5(@babel/core@8.0.1)(preact@10.29.0)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@tanstack/query-persist-client-core': specifier: workspace:* version: link:../query-persist-client-core @@ -2636,7 +3013,7 @@ importers: devDependencies: '@preact/preset-vite': specifier: ^2.10.2 - version: 2.10.5(@babel/core@7.29.7)(preact@10.29.0)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.10.5(@babel/core@8.0.1)(preact@10.29.0)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@tanstack/preact-query': specifier: workspace:* version: link:../preact-query @@ -2667,7 +3044,7 @@ importers: devDependencies: '@preact/preset-vite': specifier: ^2.10.2 - version: 2.10.5(@babel/core@7.29.7)(preact@10.29.0)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.10.5(@babel/core@8.0.1)(preact@10.29.0)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@tanstack/preact-query': specifier: workspace:* version: link:../preact-query @@ -2726,7 +3103,7 @@ importers: version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) npm-run-all2: specifier: ^5.0.0 version: 5.0.2 @@ -2738,7 +3115,7 @@ importers: version: 17.3.0 jscodeshift: specifier: 17.3.0 - version: 17.3.0(@babel/preset-env@7.29.2(@babel/core@7.29.7)) + version: 17.3.0(@babel/preset-env@7.29.2(@babel/core@8.0.1)) packages/query-core: devDependencies: @@ -2793,10 +3170,10 @@ importers: version: 5.0.2 unplugin-solid: specifier: ^2.0.0 - version: 2.0.0(@testing-library/jest-dom@6.9.1)(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) + version: 2.0.0(@testing-library/jest-dom@6.9.1)(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) packages/query-persist-client-core: dependencies: @@ -2831,7 +3208,7 @@ importers: dependencies: vitest: specifier: ^4.0.18 - version: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@7.0.2))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@7.0.2))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) devDependencies: npm-run-all2: specifier: ^5.0.0 @@ -2863,7 +3240,7 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) cpy-cli: specifier: ^5.0.0 version: 5.0.0 @@ -2897,7 +3274,7 @@ importers: version: 19.2.14 '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) npm-run-all2: specifier: ^5.0.0 version: 5.0.2 @@ -2915,10 +3292,10 @@ importers: version: 19.2.14 '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) next: specifier: ^16.0.1 - version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + version: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) npm-run-all2: specifier: ^5.0.0 version: 5.0.2 @@ -2946,7 +3323,7 @@ importers: version: 19.2.14 '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) npm-run-all2: specifier: ^5.0.0 version: 5.0.2 @@ -2974,10 +3351,10 @@ importers: version: 1.9.12 unplugin-solid: specifier: ^2.0.0 - version: 2.0.0(@testing-library/jest-dom@6.9.1)(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) + version: 2.0.0(@testing-library/jest-dom@6.9.1)(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) packages/solid-query-devtools: dependencies: @@ -2999,10 +3376,10 @@ importers: version: 1.9.12 unplugin-solid: specifier: ^2.0.0 - version: 2.0.0(@testing-library/jest-dom@6.9.1)(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) + version: 2.0.0(@testing-library/jest-dom@6.9.1)(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) packages/solid-query-persist-client: dependencies: @@ -3027,10 +3404,10 @@ importers: version: 1.9.12 unplugin-solid: specifier: ^2.0.0 - version: 2.0.0(@testing-library/jest-dom@6.9.1)(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) + version: 2.0.0(@testing-library/jest-dom@6.9.1)(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) packages/svelte-query: dependencies: @@ -3043,13 +3420,13 @@ importers: version: 2.5.8(svelte@5.55.1)(typescript@5.9.3) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@tanstack/query-test-utils': specifier: workspace:* version: link:../query-test-utils '@testing-library/svelte': specifier: ^5.2.8 - version: 5.3.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 5.3.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) '@typescript-eslint/parser': specifier: 8.58.1 version: 8.58.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) @@ -3080,13 +3457,13 @@ importers: version: 2.5.8(svelte@5.55.1)(typescript@5.9.3) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@tanstack/svelte-query': specifier: workspace:* version: link:../svelte-query '@testing-library/svelte': specifier: ^5.2.8 - version: 5.3.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 5.3.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) '@typescript-eslint/parser': specifier: 8.58.1 version: 8.58.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) @@ -3114,7 +3491,7 @@ importers: version: 2.5.8(svelte@5.55.1)(typescript@5.9.3) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@tanstack/query-test-utils': specifier: workspace:* version: link:../query-test-utils @@ -3123,7 +3500,7 @@ importers: version: link:../svelte-query '@testing-library/svelte': specifier: ^5.2.8 - version: 5.3.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 5.3.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))) '@typescript-eslint/parser': specifier: 8.58.1 version: 8.58.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) @@ -3160,7 +3537,7 @@ importers: version: link:../query-test-utils '@vitejs/plugin-vue': specifier: ^5.2.4 - version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@7.0.2)) + version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@7.0.2)) '@vue/composition-api': specifier: 1.7.2 version: 1.7.2(vue@3.5.31(typescript@7.0.2)) @@ -3188,7 +3565,7 @@ importers: version: link:../vue-query '@vitejs/plugin-vue': specifier: ^5.2.4 - version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) + version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3)) eslint-plugin-vue: specifier: ^10.5.0 version: 10.8.0(@stylistic/eslint-plugin@5.10.0(eslint@9.39.4(jiti@2.7.0)))(@typescript-eslint/parser@8.58.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3))(eslint@9.39.4(jiti@2.7.0))(vue-eslint-parser@10.4.0(eslint@9.39.4(jiti@2.7.0))) @@ -3197,7 +3574,7 @@ importers: version: 5.8.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) vue: specifier: ^3.4.27 version: 3.5.31(typescript@5.8.3) @@ -3221,78 +3598,22 @@ packages: '@adobe/css-tools@4.4.4': resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} - '@algolia/abtesting@1.1.0': - resolution: {integrity: sha512-sEyWjw28a/9iluA37KLGu8vjxEIlb60uxznfTUmXImy7H5NvbpSO6yYgmgH5KiD7j+zTUUihiST0jEP12IoXow==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-abtesting@5.35.0': - resolution: {integrity: sha512-uUdHxbfHdoppDVflCHMxRlj49/IllPwwQ2cQ8DLC4LXr3kY96AHBpW0dMyi6ygkn2MtFCc6BxXCzr668ZRhLBQ==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-analytics@5.35.0': - resolution: {integrity: sha512-SunAgwa9CamLcRCPnPHx1V2uxdQwJGqb1crYrRWktWUdld0+B2KyakNEeVn5lln4VyeNtW17Ia7V7qBWyM/Skw==} - engines: {node: '>= 14.0.0'} - '@algolia/client-common@5.2.1': resolution: {integrity: sha512-f4u3TdqU8310ffGhcCjYtTBXXnVVQ9U38Gnltayxm5Hh63BxgzJzvELUcEuOaZh31CvC1FqttKx127gF90aaQg==} engines: {node: '>= 14.0.0'} - '@algolia/client-common@5.35.0': - resolution: {integrity: sha512-ipE0IuvHu/bg7TjT2s+187kz/E3h5ssfTtjpg1LbWMgxlgiaZIgTTbyynM7NfpSJSKsgQvCQxWjGUO51WSCu7w==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-insights@5.35.0': - resolution: {integrity: sha512-UNbCXcBpqtzUucxExwTSfAe8gknAJ485NfPN6o1ziHm6nnxx97piIbcBQ3edw823Tej2Wxu1C0xBY06KgeZ7gA==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-personalization@5.35.0': - resolution: {integrity: sha512-/KWjttZ6UCStt4QnWoDAJ12cKlQ+fkpMtyPmBgSS2WThJQdSV/4UWcqCUqGH7YLbwlj3JjNirCu3Y7uRTClxvA==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-query-suggestions@5.35.0': - resolution: {integrity: sha512-8oCuJCFf/71IYyvQQC+iu4kgViTODbXDk3m7yMctEncRSRV+u2RtDVlpGGfPlJQOrAY7OONwJlSHkmbbm2Kp/w==} - engines: {node: '>= 14.0.0'} - '@algolia/client-search@5.2.1': resolution: {integrity: sha512-9os21w5CmC84FZZujufLcZPnYKuTVJ3J6LF4i1/i1BKJzy1Cbb9bTWXn+e9PGdRJBzo4DRZt0D0Pd2X5dvUucg==} engines: {node: '>= 14.0.0'} - '@algolia/client-search@5.35.0': - resolution: {integrity: sha512-FfmdHTrXhIduWyyuko1YTcGLuicVbhUyRjO3HbXE4aP655yKZgdTIfMhZ/V5VY9bHuxv/fGEh3Od1Lvv2ODNTg==} - engines: {node: '>= 14.0.0'} - - '@algolia/ingestion@1.35.0': - resolution: {integrity: sha512-gPzACem9IL1Co8mM1LKMhzn1aSJmp+Vp434An4C0OBY4uEJRcqsLN3uLBlY+bYvFg8C8ImwM9YRiKczJXRk0XA==} - engines: {node: '>= 14.0.0'} - - '@algolia/monitoring@1.35.0': - resolution: {integrity: sha512-w9MGFLB6ashI8BGcQoVt7iLgDIJNCn4OIu0Q0giE3M2ItNrssvb8C0xuwJQyTy1OFZnemG0EB1OvXhIHOvQwWw==} - engines: {node: '>= 14.0.0'} - - '@algolia/recommend@5.35.0': - resolution: {integrity: sha512-AhrVgaaXAb8Ue0u2nuRWwugt0dL5UmRgS9LXe0Hhz493a8KFeZVUE56RGIV3hAa6tHzmAV7eIoqcWTQvxzlJeQ==} - engines: {node: '>= 14.0.0'} - '@algolia/requester-browser-xhr@5.2.1': resolution: {integrity: sha512-KRDJRPEdIcej/KgqDqhUs/vhLwVh2oKYa+GaKIFGiyRaWusjwaUYdrWgiLxcHAWNKIeIpwjKnteU/dwCz+Nykg==} engines: {node: '>= 14.0.0'} - '@algolia/requester-browser-xhr@5.35.0': - resolution: {integrity: sha512-diY415KLJZ6x1Kbwl9u96Jsz0OstE3asjXtJ9pmk1d+5gPuQ5jQyEsgC+WmEXzlec3iuVszm8AzNYYaqw6B+Zw==} - engines: {node: '>= 14.0.0'} - - '@algolia/requester-fetch@5.35.0': - resolution: {integrity: sha512-uydqnSmpAjrgo8bqhE9N1wgcB98psTRRQXcjc4izwMB7yRl9C8uuAQ/5YqRj04U0mMQ+fdu2fcNF6m9+Z1BzDQ==} - engines: {node: '>= 14.0.0'} - '@algolia/requester-node-http@5.2.1': resolution: {integrity: sha512-Q9LE92zL8EZhe9+H7pwG6mMdU7RNtVrGtheM7lMfZoejpkR/DBTr2/5FCB5OsUk7iLSIwP43AKWX+2rTv0cLaA==} engines: {node: '>= 14.0.0'} - '@algolia/requester-node-http@5.35.0': - resolution: {integrity: sha512-RgLX78ojYOrThJHrIiPzT4HW3yfQa0D7K+MQ81rhxqaNyNBu4F1r+72LNHYH/Z+y9I1Mrjrd/c/Ue5zfDgAEjQ==} - engines: {node: '>= 14.0.0'} - '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -3301,53 +3622,63 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@analogjs/vite-plugin-angular@2.5.2': + resolution: {integrity: sha512-zJdmYb6B+qwMzcv9N6fWD4uYarrulqyJSPvNg8yzmVABbRV3YkAQXFMlr6ZgwkV9jSNK5CaqiSQSB238wX7RpA==} + peerDependencies: + '@angular-devkit/build-angular': ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 + '@angular/build': ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 + vite: ^6.4.1 + peerDependenciesMeta: + '@angular-devkit/build-angular': + optional: true + '@angular/build': + optional: true + vite: + optional: true + '@andrewbranch/untar.js@1.0.3': resolution: {integrity: sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw==} - '@angular-devkit/architect@0.2003.22': - resolution: {integrity: sha512-gxVOslVweD+Co6gpRVlByHus/3HVAnsl99MobS9PBh8vh2g6bJ011PBgl0TKsP/pqBGawZOkJXYrRPeMKnobYA==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@angular-devkit/architect@0.2201.8': + resolution: {integrity: sha512-EUQo8RDS1my2Bo5FRS+gBYgz1/klfIp9XESfMpTBO04nBkjF6DkPCeOxeAf1CYjWy9nCXcWn968eSdEhV5jXiA==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + hasBin: true - '@angular-devkit/core@20.3.22': - resolution: {integrity: sha512-1vZnZTAjGcCM+86v2al+2eiROiSw0uAWeVllfHSQe0KsKOP1FE8UUUiWChhxVn7vIxypphlfGunkeeIn1C/ZFw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@angular-devkit/core@22.1.8': + resolution: {integrity: sha512-34lsgg2FwMVBX7nR/ZqzRUcdvdYPvSB8XAEr2GudXAyZwLI9ehzfQlagAWR/gEb8p4uCFZW0r7uU0toxydq4Rw==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: chokidar: 5.0.0 peerDependenciesMeta: chokidar: optional: true - '@angular-devkit/schematics@20.3.22': - resolution: {integrity: sha512-gN2XSXRn3eErGEJlH0iSfQZZ7NdxVZNdjSxuVEGBEFhe3cVeC21LzM3GTWW6xwtBb4pxHglFyc7BUFiYtZiYtg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - - '@angular/animations@20.3.18': - resolution: {integrity: sha512-XFxgSyjfs0SRD2vQVFJljmM4z9nTvUoI8TRqSre/+l8D2FgzD5pG67Aj2BgDgpSFAUkIcI37G48ijK7a3ZZ3WA==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - deprecated: '@angular/animations is deprecated. Use `animate.enter` and `animate.leave` instead. For more information see: https://v22.angular.dev/guide/animations.' - peerDependencies: - '@angular/core': 20.3.18 - - '@angular/build@20.3.22': - resolution: {integrity: sha512-sxjVZU6AZHXyKRHJUMawXOj4qMf3vm8XK6wUejr01UKj6BqW2YWaQO26RpRJssXD2ITTqn6+UBwL7pEwe2a4Jg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - peerDependencies: - '@angular/compiler': ^20.0.0 - '@angular/compiler-cli': ^20.0.0 - '@angular/core': ^20.0.0 - '@angular/localize': ^20.0.0 - '@angular/platform-browser': ^20.0.0 - '@angular/platform-server': ^20.0.0 - '@angular/service-worker': ^20.0.0 - '@angular/ssr': ^20.3.22 + '@angular-devkit/schematics@22.1.8': + resolution: {integrity: sha512-Pv3cPa/44kvEwYcqwx4Ns5dhIDmcFNSHhbpheqiEG1Z/u4e2t4zHKDtE3eHZB+8o+IcC7xJj+d+AqGR44RoZDA==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + + '@angular/build@22.1.8': + resolution: {integrity: sha512-tw+Evk0EITb8p8dTu743ONoFztCEiyDkdRbtZsh7C0vBS7Q9ElsOcFeg2Z9OAAwrmtZMIBuW3jrdPRQp7OCSdw==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + '@angular/compiler': ^22.0.0 + '@angular/compiler-cli': ^22.0.0 + '@angular/core': ^22.0.0 + '@angular/localize': ^22.0.0 + '@angular/platform-browser': ^22.0.0 + '@angular/platform-server': ^22.0.0 + '@angular/service-worker': ^22.0.0 + '@angular/ssr': ^22.1.8 + istanbul-lib-instrument: ^6.0.0 karma: ^6.4.0 less: ^4.2.0 - ng-packagr: ^20.0.0 + ng-packagr: ^22.0.0 postcss: ^8.4.0 + rollup: ^4.0.0 tailwindcss: ^2.0.0 || ^3.0.0 || ^4.0.0 tslib: ^2.3.0 - typescript: '>=5.8 <6.0' - vitest: ^3.1.1 + typescript: '>=6.0 <6.1' + vitest: ^4.0.8 peerDependenciesMeta: '@angular/core': optional: true @@ -3361,6 +3692,8 @@ packages: optional: true '@angular/ssr': optional: true + istanbul-lib-instrument: + optional: true karma: optional: true less: @@ -3369,80 +3702,103 @@ packages: optional: true postcss: optional: true + rollup: + optional: true tailwindcss: optional: true vitest: optional: true - '@angular/cli@20.3.22': - resolution: {integrity: sha512-0uyQPF0gGuzioWJKNyOzWSQrrC5GiidR+8gz1lODoJTnJZZdsP5n3nvccbcRmhy55B1WByHvQBE+6eDBbh06/g==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@angular/cli@22.1.8': + resolution: {integrity: sha512-MFN/FydqDndai8vF12hDxG5RlBt1HUUheeJgJNmuHYIne4bOAfOT+xuMpIK8+gLSRwCemdqR3OMM38pnsFJ/nA==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true - '@angular/common@20.3.18': - resolution: {integrity: sha512-M62oQbSTRmnGavIVCwimoadg/PDWadgNhactMm9fgH0eM9rx+iWBAYJk4VufO0bwOhysFpRZpJgXlFjOifz/Jw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + '@angular/common@22.1.6': + resolution: {integrity: sha512-giuH+jJvo6YbBxbKofJCXvq6k8g1Z/xCAvh4piNFSSS6/toXTLCeZ+snr6Stw5b2wRbArM5Q5nDeuto3NqVPnQ==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/core': 20.3.18 + '@angular/core': 22.1.6 rxjs: ^6.5.3 || ^7.4.0 - '@angular/compiler-cli@20.3.18': - resolution: {integrity: sha512-zsoEgLgnblmRbi47YwMghKirJ8IBKJ3+I8TxLBRIBrhx+KHFp+6oeDeLyu9H+djdyk88zexVd09wzR/YK73F0g==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + '@angular/compiler-cli@22.1.6': + resolution: {integrity: sha512-C1fQuaSLnibhfbb7Im/vurdBEcfQk+/GqPkY4+dgEKd4EPleO0xWlD+k5DwyNFX8a9w7HebWfo0Zl66HuaEwOQ==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} hasBin: true peerDependencies: - '@angular/compiler': 20.3.18 - typescript: '>=5.8 <6.0' + '@angular/compiler': 22.1.6 + typescript: '>=6.0 <6.1' peerDependenciesMeta: typescript: optional: true - '@angular/compiler@20.3.18': - resolution: {integrity: sha512-AaP/LCiDNcYmF135EEozjyR04NRBT38ZfBHQwjhgwiBBTejmvcpHwJaHSkraLpZqZzE4BQqqmgiQ1EJqxEwLVA==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + '@angular/compiler@22.1.6': + resolution: {integrity: sha512-JjOUm/qD338+fGfZvxSNn/vTUiVqNwOiPzacInVUq1eVp7Jev+cnvEwXA2cFJkYZoy3Imz6wHoMvTUZNN8cbKQ==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} - '@angular/core@20.3.18': - resolution: {integrity: sha512-B+NQQngd/aDbcfW0zGLis3wTLDeHTeTYMl/mGKQH+HwdPaRCKI1wEtaXaOYVJXkP2FeThocPevB8gLwNlPQUUw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + '@angular/core@22.1.6': + resolution: {integrity: sha512-3Ln9YYOhsaU2vPufnpcu6C4dlmX4e/nJTlggVcKMT7bGZH5KlEtw3h0uh9YfANv8YhQCEk1AcuRI7KpBnh5ing==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/compiler': 20.3.18 + '@angular/compiler': 22.1.6 rxjs: ^6.5.3 || ^7.4.0 - zone.js: ~0.15.0 + zone.js: ~0.15.0 || ~0.16.0 peerDependenciesMeta: '@angular/compiler': optional: true zone.js: optional: true - '@angular/forms@20.3.18': - resolution: {integrity: sha512-x6/99LfxolyZIFUL3Wr0OrtuXHEDwEz/rwx+WzE7NL+n35yO40t3kp0Sn5uMFwI94i91QZJmXHltMpZhrVLuYg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + '@angular/forms@22.1.6': + resolution: {integrity: sha512-rfV4G4UB4l69yXSRvhaHPzTMIruvBlRO+ak9NtTcYMnsoj8O5ZCyPv0ledGIrLTBwGSI3X1j4nr9aoV+Rj/n+Q==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/common': 20.3.18 - '@angular/core': 20.3.18 - '@angular/platform-browser': 20.3.18 + '@angular/common': 22.1.6 + '@angular/core': 22.1.6 + '@angular/platform-browser': 22.1.6 rxjs: ^6.5.3 || ^7.4.0 - '@angular/platform-browser@20.3.18': - resolution: {integrity: sha512-q6s5rEN1yYazpHYp+k4pboXRzMsRB9auzTRBEhyXSGYxqzrnn3qHN0DqgsLC9WAdyhCgnIEMFA8kRT+W277DqQ==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + '@angular/platform-browser@22.1.6': + resolution: {integrity: sha512-jrRi6zpdz+jOle5l0OW7QL0a8xPgdnxWT5FrJabbiNKfYzQfqKcaAu02l8uJoJxtGb8fLQ8pbjkPpZEvKO2z+w==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/animations': 20.3.18 - '@angular/common': 20.3.18 - '@angular/core': 20.3.18 + '@angular/animations': 22.1.6 + '@angular/common': 22.1.6 + '@angular/core': 22.1.6 peerDependenciesMeta: '@angular/animations': optional: true - '@angular/router@20.3.18': - resolution: {integrity: sha512-3CWejsEYr+ze+ktvWN/qHdyq5WLrj96QZpGYJyxh1pchIcpMPE9MmLpdjf0CUrWYB7g/85u0Geq/xsz72JrGng==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + '@angular/platform-server@22.1.6': + resolution: {integrity: sha512-5daf/BngfYLnP416Wef1BFjbTxyMaY7TfqYZ26C29ScpZdPYStBoakVBM6J3k+ycjuJWt1JeaT1WJxfqchG0kA==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/common': 20.3.18 - '@angular/core': 20.3.18 - '@angular/platform-browser': 20.3.18 + '@angular/common': 22.1.6 + '@angular/compiler': 22.1.6 + '@angular/core': 22.1.6 + '@angular/platform-browser': 22.1.6 rxjs: ^6.5.3 || ^7.4.0 + '@angular/router@22.1.6': + resolution: {integrity: sha512-ex0vrkcVyJJdn7NzZXun+5ctaPPLTZJ/gE7A3g1dun7BM3g4Z6zT738mODFeJgtPtJNf4bTs2gpgvyegvzWH7w==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} + peerDependencies: + '@angular/common': 22.1.6 + '@angular/core': 22.1.6 + '@angular/platform-browser': 22.1.6 + rxjs: ^6.5.3 || ^7.4.0 + + '@angular/ssr@22.1.8': + resolution: {integrity: sha512-D/Is+0dXrFrYeWa3CGqN/inp73pvz+zMrje3wOAR22SBQSV4qPeY8Y4NuR8EflwMwsfiNAfGBYSDQs1WsEx+bQ==} + peerDependencies: + '@angular/common': ^22.0.0 + '@angular/core': ^22.0.0 + '@angular/platform-server': ^22.0.0 + '@angular/router': ^22.0.0 + peerDependenciesMeta: + '@angular/platform-server': + optional: true + '@arethetypeswrong/cli@0.15.4': resolution: {integrity: sha512-YDbImAi1MGkouT7f2yAECpUMFhhA1J0EaXzIqoC5GGtK0xDgauLtcsZezm8tNq7d3wOFXH7OnY+IORYcG212rw==} engines: {node: '>=18'} @@ -3542,18 +3898,26 @@ packages: resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} + '@babel/code-frame@8.0.0': + resolution: {integrity: sha512-dYYg153EyN2Ekbqw2zAsbd6/JR+9N2SEoC7YV2GyyqMM7x9bLDTjBD6XBhSMLH0wtIVyJj03jWNriQhaN+eoCw==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/compat-data@7.29.7': resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.3': - resolution: {integrity: sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==} - engines: {node: '>=6.9.0'} + '@babel/compat-data@8.0.0': + resolution: {integrity: sha512-DOjnob/cXOUgDOozCDeq/aK2p5y8dUIVdf6tNhEV1HQRd6I8aQ4f4fbtHRVEvb6lP3BGomrKHiS8ICAASSVQSw==} + engines: {node: ^22.18.0 || >=24.11.0} '@babel/core@7.29.7': resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} engines: {node: '>=6.9.0'} + '@babel/core@8.0.1': + resolution: {integrity: sha512-5FgxM4dLQpMJHSiVATk8foW263dVHQHBVpXYiimNECVWG01f4nFyEbQixeT6Mwvg7TayREJ2gpKl3o2RoMdnqw==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/eslint-parser@7.28.6': resolution: {integrity: sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} @@ -3565,14 +3929,26 @@ packages: resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} engines: {node: '>=6.9.0'} + '@babel/generator@8.0.0': + resolution: {integrity: sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/helper-annotate-as-pure@7.27.3': resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@8.0.0': + resolution: {integrity: sha512-NSpMkMsvvZqzThJ0p1B02cbtA2ObEyfBvq950bmNkyxsxvcxwhvvCB036rKhlEnuBBo30bOrk13u3FzlKSoRrw==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/helper-compilation-targets@7.29.7': resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@8.0.0': + resolution: {integrity: sha512-JwculLABZvyPvyLBpwU/E/IbH2uM3mnxNtIJpxnIfb24y1PrdVxK5Dqjle4DpgqpGRnwgC7G8IkzPdSXZrO1Ew==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/helper-create-class-features-plugin@7.28.6': resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==} engines: {node: '>=6.9.0'} @@ -3594,6 +3970,10 @@ packages: resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} engines: {node: '>=6.9.0'} + '@babel/helper-globals@8.0.0': + resolution: {integrity: sha512-lLozHOM6sWWlxNo8CYqHy4MBZeTvHXNgVPBfPOGsjPKUzHC2Az9QwB6gxdQmpwHl6GlQtbGgS+lj5887guDiLw==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/helper-member-expression-to-functions@7.28.5': resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} engines: {node: '>=6.9.0'} @@ -3644,14 +4024,26 @@ packages: resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@8.0.0': + resolution: {integrity: sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/helper-validator-identifier@7.29.7': resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@8.0.4': + resolution: {integrity: sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/helper-validator-option@7.29.7': resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@8.0.0': + resolution: {integrity: sha512-U4Dybxh4WESWHt5XhBeExi4DrY0/DNK1aHpQbsrQXCUbFHuMweT0TpLEWKvaraV2Y6fS+ZXunsZ8zIuZIgvF2Q==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/helper-wrap-function@7.28.6': resolution: {integrity: sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==} engines: {node: '>=6.9.0'} @@ -3660,6 +4052,10 @@ packages: resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} engines: {node: '>=6.9.0'} + '@babel/helpers@8.0.0': + resolution: {integrity: sha512-wfbi91pM3py96oIiJEz7qIpyXDytgr9zQC1HEWwlGNVRAEmItuU/0a41ZUKu1sJGyhhOIpc4t5vk4PYzt8wpsg==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/highlight@7.25.9': resolution: {integrity: sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==} engines: {node: '>=6.9.0'} @@ -3669,6 +4065,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@8.0.4': + resolution: {integrity: sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==} + engines: {node: ^22.18.0 || >=24.11.0} + hasBin: true + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} engines: {node: '>=6.9.0'} @@ -4271,14 +4672,26 @@ packages: resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} + '@babel/template@8.0.0': + resolution: {integrity: sha512-eAD0QW/AlbamBbw0FeGiwasbCVPq5ncW0HNVyLP3B9czqLyh4gvw+5JTSNt6le9+ziAU7mqDZsKTHf3jTb4chQ==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/traverse@7.29.8': resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} engines: {node: '>=6.9.0'} + '@babel/traverse@8.0.4': + resolution: {integrity: sha512-bZnmqzGG8UZneG1lLxBoWIH0G6Gr1D846Yu4/3XnY6FhCndMR49u26nTY08u/dAxWmLWF9vGQOuC+84FfIUoeg==} + engines: {node: ^22.18.0 || >=24.11.0} + '@babel/types@7.29.8': resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} engines: {node: '>=6.9.0'} + '@babel/types@8.0.4': + resolution: {integrity: sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==} + engines: {node: ^22.18.0 || >=24.11.0} + '@callstack/react-theme-provider@3.0.9': resolution: {integrity: sha512-tTQ0uDSCL0ypeMa8T/E9wAZRGKWj8kXP7+6RYgPTfOPs9N07C9xM8P02GJ3feETap4Ux5S69D9nteq9mEj86NA==} peerDependencies: @@ -5054,10 +5467,6 @@ packages: '@floating-ui/utils@0.2.11': resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} - '@gar/promise-retry@1.0.3': - resolution: {integrity: sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==} - engines: {node: ^20.17.0 || >=22.9.0} - '@gerrit0/mini-shiki@3.23.0': resolution: {integrity: sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg==} @@ -5066,6 +5475,9 @@ packages: peerDependencies: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@harperfast/extended-iterable@1.0.3': + resolution: {integrity: sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==} + '@hono/node-server@1.19.12': resolution: {integrity: sha512-txsUW4SQ1iilgE0l9/e9VQWmELXifEFvmdA1j6WFh/aFPj99hIntrSsq/if0UWyGVkmrRPKA1wCeP+UCr1B9Uw==} engines: {node: '>=18.14.1'} @@ -5245,17 +5657,21 @@ packages: resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} engines: {node: '>=18'} - '@inquirer/checkbox@4.3.2': - resolution: {integrity: sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==} - engines: {node: '>=18'} + '@inquirer/ansi@2.0.8': + resolution: {integrity: sha512-WpQM+Ti6Z40EFwwt+uL2p4UabT+W179zHp6HhLVOzfbwnVn05IPO/eXIZXGNqcT1jbQ15SujNLzQ39k4QPPxBQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + + '@inquirer/checkbox@5.2.5': + resolution: {integrity: sha512-bRt8J8m+Fot9CXv+zNQGXUq2ET0MggR1fPz7v6edN6MFYmsbfGnMmkmWZJEegMKqrAC8ej/o1sqisHZXZJMAfQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: '@types/node': optional: true - '@inquirer/confirm@5.1.14': - resolution: {integrity: sha512-5yR4IBfe0kXe59r1YCTG8WXkUbl7Z35HK87Sw+WUyGD8wNUx7JvY7laahzeytyE1oLn74bQnL7hstctQxisQ8Q==} + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} engines: {node: '>=18'} peerDependencies: '@types/node': ^22.15.3 @@ -5263,9 +5679,9 @@ packages: '@types/node': optional: true - '@inquirer/confirm@5.1.21': - resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} - engines: {node: '>=18'} + '@inquirer/confirm@6.1.1': + resolution: {integrity: sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: @@ -5281,27 +5697,45 @@ packages: '@types/node': optional: true - '@inquirer/editor@4.2.23': - resolution: {integrity: sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==} - engines: {node: '>=18'} + '@inquirer/core@11.2.1': + resolution: {integrity: sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: '@types/node': optional: true - '@inquirer/expand@4.0.23': - resolution: {integrity: sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==} - engines: {node: '>=18'} + '@inquirer/core@12.0.3': + resolution: {integrity: sha512-wsSy0sznmXwkty+2PzZwx00Cazc/E0r0B7mAzdGROz2Ct+DFZXaK7WDjGZvgjRldxH5ZhFVfF2lgkYrqgOw2KA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: '@types/node': optional: true - '@inquirer/external-editor@1.0.3': - resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} - engines: {node: '>=18'} + '@inquirer/editor@5.3.3': + resolution: {integrity: sha512-YsKkS2q63IiLtaDK/9nqzdComN97SDQrmKiyNggN+ceP4ty+Z6VwyTz3FpjeUWeW1Efss2xHFKCC9sx7hnrsxg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': ^22.15.3 + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/expand@5.1.5': + resolution: {integrity: sha512-uHuXLmXW+TtIfT/9vSBotypAkqn1n34Ul+CLGPos/xANyO4Ff5xZzkYhbKR4NEcfVK4a9mHQOpwVZzluSHFRGw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': ^22.15.3 + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/external-editor@3.0.5': + resolution: {integrity: sha512-f3QQJRIX5ZEneBHNUIuPjmbdzHnmRFJA8r2dkcb8q+OM5Uv5KtnuAttQumnrjcBVBM3mcTX1CkmtAkU58VRZxg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: @@ -5312,63 +5746,67 @@ packages: resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} engines: {node: '>=18'} - '@inquirer/input@4.3.1': - resolution: {integrity: sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==} - engines: {node: '>=18'} + '@inquirer/figures@2.0.9': + resolution: {integrity: sha512-EAWgUTGQ/Umgga51dE3B2PUHbufuXarDfg86uVgoSgNHNNQnyFKcOrQLWVqYMghuSyHh8+2HUH0Js9cTC1WAdg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + + '@inquirer/input@5.1.6': + resolution: {integrity: sha512-HtcJhB2QFVXbLuJ5S3syhNbTUVxYvwqV4VRBDkQceBloC9bmTViUoRFP5PbSaDZb3HzfPmpuU/gG4ybVBz4FHA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: '@types/node': optional: true - '@inquirer/number@3.0.23': - resolution: {integrity: sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==} - engines: {node: '>=18'} + '@inquirer/number@4.2.3': + resolution: {integrity: sha512-6Yuwh1NGSbu1Lo4N1EWjXs1jKRntLg/ZCwhmeorEHde90v1XxAozdbd4Iu30eOQLW+6h1hp2O9ujNfLSbTPJnA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: '@types/node': optional: true - '@inquirer/password@4.0.23': - resolution: {integrity: sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==} - engines: {node: '>=18'} + '@inquirer/password@5.2.2': + resolution: {integrity: sha512-W9zYdyzogK+6110mqwaSJWCBu2yA5Q/OfnGSjjZB1bNpHlmUozXxTl0+QOZBNeVd6Qo81/qT75gW05gLAtITxw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: '@types/node': optional: true - '@inquirer/prompts@7.8.2': - resolution: {integrity: sha512-nqhDw2ZcAUrKNPwhjinJny903bRhI0rQhiDz1LksjeRxqa36i3l75+4iXbOy0rlDpLJGxqtgoPavQjmmyS5UJw==} - engines: {node: '>=18'} + '@inquirer/prompts@8.5.2': + resolution: {integrity: sha512-IYR/3C/paEVVQYQvdDlFZVjRCJVYHHON0XXMH91KO9GSxs0TdKYWlUdvfQl2EfAHDxUaN3IBffkE/BDTh5nJ6g==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: '@types/node': optional: true - '@inquirer/rawlist@4.1.11': - resolution: {integrity: sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==} - engines: {node: '>=18'} + '@inquirer/rawlist@5.3.5': + resolution: {integrity: sha512-1oHky1ONfCOwNrnkQGDE1oaSij/3fI6HFMSf2H/WsGO2lEyDX9My82iggITSy9ddSZ8yk8j9v41OI0fVoSIoaA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: '@types/node': optional: true - '@inquirer/search@3.2.2': - resolution: {integrity: sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==} - engines: {node: '>=18'} + '@inquirer/search@4.3.3': + resolution: {integrity: sha512-fyuIU1Nbpvwlikjg3gXwJFDI11+EFjqQ7P+iByfmivIKQ1vmaykNrD/vy5unHuUqUpsOsnvJ25//tPF7E/RBRA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: '@types/node': optional: true - '@inquirer/select@4.4.2': - resolution: {integrity: sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==} - engines: {node: '>=18'} + '@inquirer/select@5.2.5': + resolution: {integrity: sha512-9kc15hr8r/kI+3DO/xLog5nOzTz1jqsHXa6JBFzmQKhkoJ8Slda1I1L/uD8ZSZ9tF1yp79wwXe7mclvX1rqR2Q==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': ^22.15.3 peerDependenciesMeta: @@ -5384,6 +5822,15 @@ packages: '@types/node': optional: true + '@inquirer/type@4.1.1': + resolution: {integrity: sha512-yJoHYrMnxIsJZCY+0Vb66Dy3he3kL3e2wOBKhoSwWWAzZAY82emlxwgprCtp6yRixvNRNq9ztfRWQYPNr3Go7A==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': ^22.15.3 + peerDependenciesMeta: + '@types/node': + optional: true + '@internationalized/date@3.12.0': resolution: {integrity: sha512-/PyIMzK29jtXaGU23qTvNZxvBXRtKbNnGDFD+PY6CZw/Y8Ex8pFUzkuCJCG9aOqmShjqhS9mPqP6Dk5onQY8rQ==} @@ -5518,12 +5965,12 @@ packages: peerDependencies: solid-js: ^1.8.8 - '@listr2/prompt-adapter-inquirer@3.0.1': - resolution: {integrity: sha512-3XFmGwm3u6ioREG+ynAQB7FoxfajgQnMhIu8wC5eo/Lsih4aKDg0VuIMGaOsYn7hJSJagSeaD4K8yfpkEoDEmA==} - engines: {node: '>=20.0.0'} + '@listr2/prompt-adapter-inquirer@4.2.5': + resolution: {integrity: sha512-pYGy9dTdTwXdasPgyohkr0HoQ4FrkAzFnsUZl/gcnadDArbpZ8e+fgr+F9WBdNEl2y00mb9bCM4WgmoBkZJ27A==} + engines: {node: '>=22.13.0'} peerDependencies: - '@inquirer/prompts': '>= 3 < 8' - listr2: 9.0.1 + '@inquirer/prompts': '>= 3 < 9' + listr2: 11.0.0 '@lit-labs/ssr-client@1.1.8': resolution: {integrity: sha512-PjGh81oKsoI64m3IDjTqqjhC7dr2uC/o0jrllUb5gRAyp/RlAHxapgJrjq9kWz97faCHLQ8jUlTi6tGm+8fgyA==} @@ -5541,38 +5988,38 @@ packages: '@lit/reactive-element@2.1.2': resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==} - '@lmdb/lmdb-darwin-arm64@3.4.2': - resolution: {integrity: sha512-NK80WwDoODyPaSazKbzd3NEJ3ygePrkERilZshxBViBARNz21rmediktGHExoj9n5t9+ChlgLlxecdFKLCuCKg==} + '@lmdb/lmdb-darwin-arm64@3.5.6': + resolution: {integrity: sha512-mY5FG4TjPAkY4P0w+OhHaUka5mDh2TX2WKYIwuKzJ1zeW3VvRgxdam/lGJTquI+bthTx5CSHDW+BAQCnNAzkEA==} cpu: [arm64] os: [darwin] - '@lmdb/lmdb-darwin-x64@3.4.2': - resolution: {integrity: sha512-zevaowQNmrp3U7Fz1s9pls5aIgpKRsKb3dZWDINtLiozh3jZI9fBrI19lYYBxqdyiIyNdlyiidPnwPShj4aK+w==} + '@lmdb/lmdb-darwin-x64@3.5.6': + resolution: {integrity: sha512-foa+pwitysO8k+xhs7psBFfTKnVgR69NlZRRTHaFVDqphh7AdGpLeyRzKw/ofatr/sN6TiHRRW6mmop0ZrrppQ==} cpu: [x64] os: [darwin] - '@lmdb/lmdb-linux-arm64@3.4.2': - resolution: {integrity: sha512-ZBEfbNZdkneebvZs98Lq30jMY8V9IJzckVeigGivV7nTHJc+89Ctomp1kAIWKlwIG0ovCDrFI448GzFPORANYg==} + '@lmdb/lmdb-linux-arm64@3.5.6': + resolution: {integrity: sha512-HmiyFFdJa38s1heCMSooSPaBSFTHJ3C+ERPp28xAPlDX1YiALJVOgbry065nXd8Y7KISWjnw05zpG1RX8IfftA==} cpu: [arm64] os: [linux] - '@lmdb/lmdb-linux-arm@3.4.2': - resolution: {integrity: sha512-OmHCULY17rkx/RoCoXlzU7LyR8xqrksgdYWwtYa14l/sseezZ8seKWXcogHcjulBddER5NnEFV4L/Jtr2nyxeg==} + '@lmdb/lmdb-linux-arm@3.5.6': + resolution: {integrity: sha512-QR4YRyR5h5Z8eGXrNQjiyo2NNDfqi3tCc9dQG5Is1blCt+qWw1ZoBWhlWAr5d+jshkifMIJjVHzHGKbkKzF8Tw==} cpu: [arm] os: [linux] - '@lmdb/lmdb-linux-x64@3.4.2': - resolution: {integrity: sha512-vL9nM17C77lohPYE4YaAQvfZCSVJSryE4fXdi8M7uWPBnU+9DJabgKVAeyDb84ZM2vcFseoBE4/AagVtJeRE7g==} + '@lmdb/lmdb-linux-x64@3.5.6': + resolution: {integrity: sha512-ADzCuCF2cTNiX9kDScqcz1fjnAkxPpQNneV3KFTdV3wWtVlI2sTGzySoMTgDpinkMMFj1NTJlxA6XR8fwc4hlA==} cpu: [x64] os: [linux] - '@lmdb/lmdb-win32-arm64@3.4.2': - resolution: {integrity: sha512-SXWjdBfNDze4ZPeLtYIzsIeDJDJ/SdsA0pEXcUBayUIMO0FQBHfVZZyHXQjjHr4cvOAzANBgIiqaXRwfMhzmLw==} + '@lmdb/lmdb-win32-arm64@3.5.6': + resolution: {integrity: sha512-J7A9aEQsQiv0TYtBGL7NDIPp2lOS8nnl+zm4sWZm1xlsTTaQ4PgD096Adzdrk27rw3UxCkDXdCUa4ax41oztBQ==} cpu: [arm64] os: [win32] - '@lmdb/lmdb-win32-x64@3.4.2': - resolution: {integrity: sha512-IY+r3bxKW6Q6sIPiMC0L533DEfRJSXibjSI3Ft/w9Q8KQBNqEIvUFXt+09wV8S5BRk0a8uSF19YWxuRwEfI90g==} + '@lmdb/lmdb-win32-x64@3.5.6': + resolution: {integrity: sha512-1g7G0knRX2iV/voDu54yxrGqw5Dk0w2oIYb7dgJq8IkOi+m7wbD8Q3QpPFjh0C01G58S88dqGn03len6UPCXsg==} cpu: [x64] os: [win32] @@ -5606,8 +6053,8 @@ packages: '@microsoft/tsdoc@0.15.1': resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==} - '@modelcontextprotocol/sdk@1.26.0': - resolution: {integrity: sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==} + '@modelcontextprotocol/sdk@1.30.0': + resolution: {integrity: sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==} engines: {node: '>=18'} peerDependencies: '@cfworker/json-schema': ^4.1.1 @@ -5962,47 +6409,10 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@npmcli/agent@4.0.0': - resolution: {integrity: sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA==} - engines: {node: ^20.17.0 || >=22.9.0} - '@npmcli/fs@3.1.1': resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - '@npmcli/fs@5.0.0': - resolution: {integrity: sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==} - engines: {node: ^20.17.0 || >=22.9.0} - - '@npmcli/git@7.0.2': - resolution: {integrity: sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==} - engines: {node: ^20.17.0 || >=22.9.0} - - '@npmcli/installed-package-contents@4.0.0': - resolution: {integrity: sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA==} - engines: {node: ^20.17.0 || >=22.9.0} - hasBin: true - - '@npmcli/node-gyp@5.0.0': - resolution: {integrity: sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==} - engines: {node: ^20.17.0 || >=22.9.0} - - '@npmcli/package-json@7.0.5': - resolution: {integrity: sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ==} - engines: {node: ^20.17.0 || >=22.9.0} - - '@npmcli/promise-spawn@9.0.1': - resolution: {integrity: sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==} - engines: {node: ^20.17.0 || >=22.9.0} - - '@npmcli/redact@4.0.0': - resolution: {integrity: sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==} - engines: {node: ^20.17.0 || >=22.9.0} - - '@npmcli/run-script@10.0.4': - resolution: {integrity: sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg==} - engines: {node: ^20.17.0 || >=22.9.0} - '@nx/nx-darwin-arm64@22.1.3': resolution: {integrity: sha512-4D/jXGsr3jcQ0vBo8aXXZMdfmC3n4OsZ1zjFaOXlF62Ujug+RqI/IvKxycT9r7Lr09PmW2OqBC01NfIWKoBLhg==} cpu: [arm64] @@ -6069,48 +6479,146 @@ packages: '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + '@oxc-parser/binding-android-arm-eabi@0.121.0': + resolution: {integrity: sha512-n07FQcySwOlzap424/PLMtOkbS7xOu8nsJduKL8P3COGHKgKoDYXwoAHCbChfgFpHnviehrLWIPX0lKGtbEk/A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-parser/binding-android-arm-eabi@0.142.0': + resolution: {integrity: sha512-ZiRGDutGsv1G6bL/ozy/koC0Sv39T1DqyoC4KD1DOy9ZoACm1O5UWhEK2c02Qdk+4lfLVkvFa/mQ0fm/4h1BtQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + '@oxc-parser/binding-android-arm-eabi@0.143.0': resolution: {integrity: sha512-n9uozULWflPqBtdmI8lAabLqGKNgLVNN0ZH8HfgCwpKGNtzRzauB76jTiW/3YLkcA7N1zskpi9GdVnZuu1SAvg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] + '@oxc-parser/binding-android-arm64@0.121.0': + resolution: {integrity: sha512-/Dd1xIXboYAicw+twT2utxPD7bL8qh7d3ej0qvaYIMj3/EgIrGR+tSnjCUkiCT6g6uTC0neSS4JY8LxhdSU/sA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-parser/binding-android-arm64@0.142.0': + resolution: {integrity: sha512-WZkvGRLNQTz8lR9zP5nLjUdlroRCopBu3g9zF1p/laE6DzT1UbQo8Rdz5MWhaJUPYg/6gp+jo7HUgsyKaN1FtQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@oxc-parser/binding-android-arm64@0.143.0': resolution: {integrity: sha512-9BbdjHETk6O3zH/DDid9IgBtF0GlpLabNKN231uraXpRDSfY+iiZxTP5bk1Z63GBownVdhdINFIeddmMz4MzpQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] + '@oxc-parser/binding-darwin-arm64@0.121.0': + resolution: {integrity: sha512-A0jNEvv7QMtCO1yk205t3DWU9sWUjQ2KNF0hSVO5W9R9r/R1BIvzG01UQAfmtC0dQm7sCrs5puixurKSfr2bRQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-parser/binding-darwin-arm64@0.142.0': + resolution: {integrity: sha512-l4khS8LQOOVYsGRVARo1gSaCT/aBSceUVXgtovWc2+drnxVuDr082WA3OCHVdVzIz5JIrP/y9CWsSKxBDNmYGg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@oxc-parser/binding-darwin-arm64@0.143.0': resolution: {integrity: sha512-gh+6ecoHUy4/sUcolBl/1qPXKBbYNxFY0Pk0ujgQvINTMSftJY7o4yb8gOkDJPeZeB8+a+u7xTe6umoP8N5HFA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] + '@oxc-parser/binding-darwin-x64@0.121.0': + resolution: {integrity: sha512-SsHzipdxTKUs3I9EOAPmnIimEeJOemqRlRDOp9LIj+96wtxZejF51gNibmoGq8KoqbT1ssAI5po/E3J+vEtXGA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-parser/binding-darwin-x64@0.142.0': + resolution: {integrity: sha512-QBsNF3nqlXmcH2B1YOPqQYmCJoy4HuIjUxGbBO/k5JAJUl68ghU2psRY2zPk+RyBaWqKP/qfL4oaFgEMCdwskA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@oxc-parser/binding-darwin-x64@0.143.0': resolution: {integrity: sha512-qd1hl2d+lXgHv/VQ/M9qm8TrMC5T4RqDBwtOnl+1D0QMjwcz+8AaB4JSg8STgeag0GP6a6L74XEGAsrTSJWNzQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] + '@oxc-parser/binding-freebsd-x64@0.121.0': + resolution: {integrity: sha512-v1APOTkCp+RWOIDAHRoaeW/UoaHF15a60E8eUL6kUQXh+i4K7PBwq2Wi7jm8p0ymID5/m/oC1w3W31Z/+r7HQw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-parser/binding-freebsd-x64@0.142.0': + resolution: {integrity: sha512-b7Q7m4Cqc6XqNhri3R+QhU+GVy646Pn+bkdhrDdWym/Fdi0ZUa+d73H9dm5H91JtbtAQ/z1d8XKMW3oOV8a4tQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@oxc-parser/binding-freebsd-x64@0.143.0': resolution: {integrity: sha512-M5XXcNa7aOqLPKTR41msfghKu2yQ4xWvCm11/gwU0JzOzHNk5sgW//rVEjJ+LO48+VDAMzXTSzurUVxIDKwozw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] + '@oxc-parser/binding-linux-arm-gnueabihf@0.121.0': + resolution: {integrity: sha512-PmqPQuqHZyFVWA4ycr0eu4VnTMmq9laOHZd+8R359w6kzuNZPvmmunmNJ8ybkm769A0nCoVp3TJ6dUz7B3FYIQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-gnueabihf@0.142.0': + resolution: {integrity: sha512-3riVS5IhdH3uCZj1Y9ftDQlR0dvLsIlw/edrRqk8JhgNd5K0XSs+UBtgh50N13CAlW9/TXj6sVGXaKNBocd0Yg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@oxc-parser/binding-linux-arm-gnueabihf@0.143.0': resolution: {integrity: sha512-T/GXusuOkPNQhCQCSBbcU/N8j0rAypuDBl1IyFK+lyYT594XsVz80clPC/OtbSSpBGyJxj8uYEfctxVuxVYoww==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@oxc-parser/binding-linux-arm-musleabihf@0.121.0': + resolution: {integrity: sha512-vF24htj+MOH+Q7y9A8NuC6pUZu8t/C2Fr/kDOi2OcNf28oogr2xadBPXAbml802E8wRAVfbta6YLDQTearz+jw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-musleabihf@0.142.0': + resolution: {integrity: sha512-NmXUOpgpTSkhl795TiXmWppTwmSJ92RC1qvD6e4XOF+slgmo3e6Ah+kEu+6AN8s7NAOEwqGmir58MgSQSWmBSA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@oxc-parser/binding-linux-arm-musleabihf@0.143.0': resolution: {integrity: sha512-oKu4RcBlXSqo3OC62dp6YTnQaZIurNDpCX3BnAM3+bJxt7s8J2TJKMnC0UYer1qhlRaDCg6wkTaTw+2IlsZ12w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@oxc-parser/binding-linux-arm64-gnu@0.121.0': + resolution: {integrity: sha512-wjH8cIG2Lu/3d64iZpbYr73hREMgKAfu7fqpXjgM2S16y2zhTfDIp8EQjxO8vlDtKP5Rc7waZW72lh8nZtWrpA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-arm64-gnu@0.142.0': + resolution: {integrity: sha512-gc0EXsKtXgerujmU2Bql3u1L1HsSQ2774R83idq/FoNMPVV/RY/1ErFsvnit7KoiP/sLvzQixeUo4Ut0ic0wmw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-arm64-gnu@0.143.0': resolution: {integrity: sha512-WJBbD186AZmMGaSIhlktC+rPl8L3peCTXAh88Ih9uEvK0en2mPojGyCGYiL6mHtV1RPV3JyfJW5t6n5hh0lXhA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6118,6 +6626,20 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-arm64-musl@0.121.0': + resolution: {integrity: sha512-qT663J/W8yQFw3dtscbEi9LKJevr20V7uWs2MPGTnvNZ3rm8anhhE16gXGpxDOHeg9raySaSHKhd4IGa3YZvuw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-arm64-musl@0.142.0': + resolution: {integrity: sha512-F2XvmWSE0uWpie+jHKKIFgdVOe9ypGhkEZxKx5DuW215K6cbAC274yYaPkcM7EqY4Df3Weyhpcz3lsURyH2LVg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@oxc-parser/binding-linux-arm64-musl@0.143.0': resolution: {integrity: sha512-t1AcYOwEzgceadT4v5e+vaCCb0AncCA3v5AyzfBAz/tMq11qzVccXKzNHtkWdjBsgvTKwRkaUF3QvT4kot8vcQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6125,6 +6647,20 @@ packages: os: [linux] libc: [musl] + '@oxc-parser/binding-linux-ppc64-gnu@0.121.0': + resolution: {integrity: sha512-mYNe4NhVvDBbPkAP8JaVS8lC1dsoJZWH5WCjpw5E+sjhk1R08wt3NnXYUzum7tIiWPfgQxbCMcoxgeemFASbRw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-ppc64-gnu@0.142.0': + resolution: {integrity: sha512-wLMbT21U/QxknQsk+VvNF0b9D2/aGWhcaQQQ+VYlE8FwD5+GoWZIPPXNzyHmkYyhm0KB3itL+TBavjMatqNnYA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-ppc64-gnu@0.143.0': resolution: {integrity: sha512-RsnO/NoD8376LMJq8JS8TwI0ieNaFRTuNe2GVJntQg6gwZNMENZsEbknHdVwjpOmxdGLGodcwaGSbAeRr5Bgjw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6132,6 +6668,20 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-riscv64-gnu@0.121.0': + resolution: {integrity: sha512-+QiFoGxhAbaI/amqX567784cDyyuZIpinBrJNxUzb+/L2aBRX67mN6Jv40pqduHf15yYByI+K5gUEygCuv0z9w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-gnu@0.142.0': + resolution: {integrity: sha512-+G8F/4ckwT7FCJV4H2bt09xEzJbjNCfuL4Sp1AYNaFtFMVtgIGMuJlteT82U+K0UIZ/DzAR/LDlMFnEuajG7Kw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-riscv64-gnu@0.143.0': resolution: {integrity: sha512-48fSVfR9TZi5CASZFyv0VC6z6BCoeihFsX031mAD/oSH7d9PYsPgIqza7d9mjP7Z2KTEpTFyH6SIu0Ui6R1vdg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6139,6 +6689,20 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-riscv64-musl@0.121.0': + resolution: {integrity: sha512-9ykEgyTa5JD/Uhv2sttbKnCfl2PieUfOjyxJC/oDL2UO0qtXOtjPLl7H8Kaj5G7p3hIvFgu3YWvAxvE0sqY+hQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-riscv64-musl@0.142.0': + resolution: {integrity: sha512-hTsHtTLxMAfCo+rpF5K3qZJKW2NpPN/CHd4mYB3y7XlSdspHkd2gehDIofP64AacA9nWQw2tY3O7wR6UY8IVOA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + '@oxc-parser/binding-linux-riscv64-musl@0.143.0': resolution: {integrity: sha512-T8CpdD+SfE01DnIOD4HpVxu0ZJOfMJ/VhCvikKfaXAxkZ+9veyLM/D2hpi7Y2hFUyPmVQO3FNZHmYzV/WlVR4g==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6146,6 +6710,20 @@ packages: os: [linux] libc: [musl] + '@oxc-parser/binding-linux-s390x-gnu@0.121.0': + resolution: {integrity: sha512-DB1EW5VHZdc1lIRjOI3bW/wV6R6y0xlfvdVrqj6kKi7Ayu2U3UqUBdq9KviVkcUGd5Oq+dROqvUEEFRXGAM7EQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-s390x-gnu@0.142.0': + resolution: {integrity: sha512-6y7qYY3TCUDYjqswImdTGl92y+KA/80twALegQPN27kfY+bG7Ib1+L3jbmrCZQx6wrVnai9IPsEZp07I0hx7JQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-s390x-gnu@0.143.0': resolution: {integrity: sha512-QLdeMsCcacenPEFsfxnBUDF1y6opyz5+fmOz9bfD5Y7fiGCMupUCuB3KTPQhNwshIG1P9fPqar9MHxuBDd4bwQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6153,6 +6731,20 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-x64-gnu@0.121.0': + resolution: {integrity: sha512-s4lfobX9p4kPTclvMiH3gcQUd88VlnkMTF6n2MTMDAyX5FPNRhhRSFZK05Ykhf8Zy5NibV4PbGR6DnK7FGNN6A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-gnu@0.142.0': + resolution: {integrity: sha512-i69kAWU+2LgoH5bR+zWiiu+UzAw7Oxkwv7COeJTeY19pn4e70nKQcr9Pm6cL2Z0Z54d+gl9qADlK/0yyuCPiBA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-x64-gnu@0.143.0': resolution: {integrity: sha512-659ujfqLy6k7cuH3sbzhd8b+ztSq+i6E2E9pG78Q0BmHjAExfGIdgc8cGgMdwAozDXeZFHkJ+LXYJdWsaGdgyw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6160,6 +6752,20 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-x64-musl@0.121.0': + resolution: {integrity: sha512-P9KlyTpuBuMi3NRGpJO8MicuGZfOoqZVRP1WjOecwx8yk4L/+mrCRNc5egSi0byhuReblBF2oVoDSMgV9Bj4Hw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-x64-musl@0.142.0': + resolution: {integrity: sha512-4SQs678MmjYVrmhAgCWD4o0vpaFszXw9xLX5p2Z9MMFcltxiLkA88wQjh80YHjPrXtpyZ2CWI5m+1yNKM0m2Pw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@oxc-parser/binding-linux-x64-musl@0.143.0': resolution: {integrity: sha512-/Mw/9j4TfZcnKphPrzOE6t4MMknXadcAAuVUlDRTF/ETWB5xOgQvOJV2Mh9We/bWxZdoxaGAdc+hy4GuYwQ2yQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6167,30 +6773,97 @@ packages: os: [linux] libc: [musl] + '@oxc-parser/binding-openharmony-arm64@0.121.0': + resolution: {integrity: sha512-R+4jrWOfF2OAPPhj3Eb3U5CaKNAH9/btMveMULIrcNW/hjfysFQlF8wE0GaVBr81dWz8JLgQlsxwctoL78JwXw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-parser/binding-openharmony-arm64@0.142.0': + resolution: {integrity: sha512-YHpx9N7Ln3a++Tc8rv+H7mrK1zyJQOAwCFg8LZ3lTs1T5afGWeZrLPhPT9HLnIwSjCyJqPWVMIrMxbjcmBr2oQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@oxc-parser/binding-openharmony-arm64@0.143.0': resolution: {integrity: sha512-8rIKWR2BFuifbIK/1XB9wTaSdtuJ25dlE7ZQYDnEwj/2xH2vHsxnvIjHT3ZjSVuLLwGGlSslIG/fbOJ8TV8rTw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] + '@oxc-parser/binding-wasm32-wasi@0.121.0': + resolution: {integrity: sha512-5TFISkPTymKvsmIlKasPVTPuWxzCcrT8pM+p77+mtQbIZDd1UC8zww4CJcRI46kolmgrEX6QpKO8AvWMVZ+ifw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@oxc-parser/binding-wasm32-wasi@0.142.0': + resolution: {integrity: sha512-3pLDyY3+oogW73RM5uehNgAiR/Xfb7fvO2Q1Z1gIqZ2+50XDVQmBVlRkHXZTU4gKnQHpwETNsYQVsJ3joVB2iA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@oxc-parser/binding-win32-arm64-msvc@0.121.0': + resolution: {integrity: sha512-V0pxh4mql4XTt3aiEtRNUeBAUFOw5jzZNxPABLaOKAWrVzSr9+XUaB095lY7jqMf5t8vkfh8NManGB28zanYKw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-parser/binding-win32-arm64-msvc@0.142.0': + resolution: {integrity: sha512-Had/VeVY28Oyb0K+Q4FV8KCzoBycIh93oDK6pCbya9lkzdq+ikMHMgBubsdqqlybjJmQRawCQRrnBRHyQwYvcQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@oxc-parser/binding-win32-arm64-msvc@0.143.0': resolution: {integrity: sha512-5U9kQYMfRRI6Zq7KDxgbIP0RMnKrfn3gLepRMgJuRkPSUALTiRCk9d/uyhb4lGDjUdzwK7mBkKqhLgzBPCmLpQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] + '@oxc-parser/binding-win32-ia32-msvc@0.121.0': + resolution: {integrity: sha512-4Ob1qvYMPnlF2N9rdmKdkQFdrq16QVcQwBsO8yiPZXof0fHKFF+LmQV501XFbi7lHyrKm8rlJRfQ/M8bZZPVLw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-parser/binding-win32-ia32-msvc@0.142.0': + resolution: {integrity: sha512-GGi3+YphVHavvgs6gum2UXoNCqzHAmPt/nXkn8ZQZstV2Q1qZD1Mn8fz/nWrDkefHQtrG/+1/XrbMxsBTo6Svw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + '@oxc-parser/binding-win32-ia32-msvc@0.143.0': resolution: {integrity: sha512-25P7AaHk4R88Yv2XH4gToDVmh0cOu+bEURQU10CRrmvgabfRArSGAP5osmwUKeSUHj0VS50upbpbRWWW/m7mHA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] + '@oxc-parser/binding-win32-x64-msvc@0.121.0': + resolution: {integrity: sha512-BOp1KCzdboB1tPqoCPXgntgFs0jjeSyOXHzgxVFR7B/qfr3F8r4YDacHkTOUNXtDgM8YwKnkf3rE5gwALYX7NA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@oxc-parser/binding-win32-x64-msvc@0.142.0': + resolution: {integrity: sha512-Ny/Wv4Us1LGC/ljwNTp+Hx3r/pH15EFfeDF0p+n898gt+TtRd6C9SccHcuUhDiNTb8s5tt7jdeAMDRQZ4Vq6hg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@oxc-parser/binding-win32-x64-msvc@0.143.0': resolution: {integrity: sha512-ORMh3JE1s6V7ySicdRK7vgaDQnn5o+UHg9ct989PlWHbel8O9ARrmWXM6kZjrBMtNucxNayQ8g69G0VfWzhANw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] + '@oxc-project/types@0.121.0': + resolution: {integrity: sha512-CGtOARQb9tyv7ECgdAlFxi0Fv7lmzvmlm2rpD/RdijOO9rfk/JvB1CjT8EnoD+tjna/IYgKKw3IV7objRb+aYw==} + + '@oxc-project/types@0.140.0': + resolution: {integrity: sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==} + + '@oxc-project/types@0.142.0': + resolution: {integrity: sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==} + '@oxc-project/types@0.143.0': resolution: {integrity: sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==} @@ -6571,36 +7244,73 @@ packages: resolution: {integrity: sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==} engines: {node: '>=14.0.0'} + '@rolldown/binding-android-arm64@1.2.0': + resolution: {integrity: sha512-9yB1l95IrJuNGDFdOYe79vdApdz6WWBCObE+rQ2LUliYUlcyFwSYIb2xb5/Ifw7dAtMy2ZqNyd8QTSOc7duAKw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@rolldown/binding-android-arm64@1.2.4': resolution: {integrity: sha512-jHC2cnyKz5xU2fhECtFl8OZ83cYNt13GZQD+0uMJ/X3o+ijmd56okHhTUwxVSHPx1IRVIJEZ1/1pPzeLCU6XKA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] + '@rolldown/binding-darwin-arm64@1.2.0': + resolution: {integrity: sha512-pexNaW9ACLUOaBITOpU6qVu4VrsOFIjTv6bzgu0YUATo4eUJx0V605PxwZfndpPOn0ilqGqvGQ0M8UW0IE24jg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@rolldown/binding-darwin-arm64@1.2.4': resolution: {integrity: sha512-Dc5mPD8F5F/FS8i01syd7FTF6yB2fVthH/TRkjwJkzUK6EpoxHtqvZQP5Zwq80/5z19TWYHIg1KOHboCgVx/aQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] + '@rolldown/binding-darwin-x64@1.2.0': + resolution: {integrity: sha512-NqKYaq0355ZmNMG4QGpxtEDxsc7tGDhjhCm4PpE0cwnBW+5Il95LJyq414niEiaKLVjnVHBEjSo1wngKxJNiFw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@rolldown/binding-darwin-x64@1.2.4': resolution: {integrity: sha512-fpDm4oBo6SqLvWUYCmFhdde3U9KH2fRNNMeAnAPAIwxRL345xutL0EtEUcuoxsoazdJGv/MuDBQHlCDrtbvqOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] + '@rolldown/binding-freebsd-x64@1.2.0': + resolution: {integrity: sha512-3vPoHzh6eBTz9IbB0/qZdSr0Qeks2echn+I4cHu2joV74VriPDdldswksEDzrl1mBB+oPRi+67+3Ib59paxIPQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@rolldown/binding-freebsd-x64@1.2.4': resolution: {integrity: sha512-rSJoreDE/HoIzoaib6MTp5jQtCTdMHKIvItAKT/ImS6Y6Ww76oUaeMyp4Vc/fAgd/ehji068IxetHXAnqUwN9A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] + '@rolldown/binding-linux-arm-gnueabihf@1.2.0': + resolution: {integrity: sha512-E6NNefZ1bUVmKJq2tJkf45J4Zyczj7qm9rUT7NY+Xo2474Y13qWAwc2tvBt0BAVbmtXR1llkxXg0Ou1jbDf2SQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@rolldown/binding-linux-arm-gnueabihf@1.2.4': resolution: {integrity: sha512-/jm8OGHgn7oGaJu3i/qZI9spUGcJ+y/lk43ttQ/iO1tOd9NissG6o97bighBCiL+BKRngmcDuR6ikfwYdJmVuQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@rolldown/binding-linux-arm64-gnu@1.2.0': + resolution: {integrity: sha512-D+TgkdgM1vu+7/Fpf8+v0ARW+RXEP9Ccazgm8zQ4JFFd9Q7SrYQ2TakU5S5ihazQDgpKyAgZDOcIFsvoHmTZ8w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-arm64-gnu@1.2.4': resolution: {integrity: sha512-tIP06BeD9EqvECBrPZ+sqdPlYrT+aYaAiu1wYziVx5elRK/ftm33JxVDy2bXGbr6J0CrtirCkR87/X5a2euEng==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6608,6 +7318,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-arm64-musl@1.2.0': + resolution: {integrity: sha512-wUqdwJBbAv0APN87GecstdMUtLjjNTs0hBALpxETD73mccFxdmt/XeizXDtN5RAlBwNKmI+Tg+blect2G+8IeQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@rolldown/binding-linux-arm64-musl@1.2.4': resolution: {integrity: sha512-Ql1Q0EQqVThvn9VAVlwNzsUvbSFtCMGjLpRRi4pk5i7NZZ4n5ISiLMjHYtus4VQ2PvkSw24zyaCVsiS+sXPj1w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6615,6 +7332,13 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-ppc64-gnu@1.2.0': + resolution: {integrity: sha512-9DtF35qR9/NrfhM4oxLplCzVVjE+KKm8Pjemi0i/sdhAWkUasjmSo8WTTubNJClhSHCfyk2yeyoXDQEDPtDAAw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-ppc64-gnu@1.2.4': resolution: {integrity: sha512-GjbjXD4XXfN19D0LZNbmiCBUoDiRACsYHr0yaIbbn8aFsXjHZifcYqu/W5Er5X2X990WjHXFrxarn5chzItorQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6622,6 +7346,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.2.0': + resolution: {integrity: sha512-RzuHrBh8X8Hntd2N4VR02QGEciq/9JhcZoTpR/Cee6otRrlILGCf3cg2ygHuih+ZebUnWmMrDX6ITI85btO6rQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.2.4': resolution: {integrity: sha512-p5WR0NOwaRmJ/B1b6IjEFLLivwEsf3PrdBIhRbhTCQisbo2SvHHpG4ELB/+FgQNnB88LTOF86upmJmbvZdQ2lw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6629,6 +7360,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.2.0': + resolution: {integrity: sha512-MK7L0018jjh1jR3mh21G2j1zAVcpscJBlPo2z19pRjv2XOYGRhaV4LyiD8HO6nCDdZln9IFgCMIV5yt4E3klGQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.2.4': resolution: {integrity: sha512-4/GyVjmhR+Tc6HLJvwc1sOhPqAZtySiSMesOZyX6JQ5XBxoTDEMKQzvo07NIK6nTon/SivlZqvhzvuVBNQhObQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6636,6 +7374,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-x64-musl@1.2.0': + resolution: {integrity: sha512-gyrxLQ9NfGb/9LoVnC4kb9miUghw1mghnkfYvNHSnVIXriabnfgGPUP4RLcJm87q3KgYz4FYUG8IDiWUT+CpSw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@rolldown/binding-linux-x64-musl@1.2.4': resolution: {integrity: sha512-l9eeLsCNvPpmSXUej0etw/J1eqV0Jj1D5G/xG6YTijmE6dkv6E2QezgWbTfQk63v952DPqrjOCoiqxq7Bw0YUQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6643,18 +7388,41 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-openharmony-arm64@1.2.0': + resolution: {integrity: sha512-/6VFMQGRmrhP77KXDC+StIxGzcNp5JOIyYtw0CQ8gPlzhpiIRucYfoM5FaFamHd5BJYIdH86yfP46l1p3WdrFA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@rolldown/binding-openharmony-arm64@1.2.4': resolution: {integrity: sha512-e0F355MSTMm3+UOqtV3L24gFUp2N5m1f8L/7d56deik6va+AXdrt9F8LbzGpeWGWRbZEDq4m8NVnJDeBtf9DZg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] + '@rolldown/binding-wasm32-wasi@1.2.0': + resolution: {integrity: sha512-rwdbUL465kisF24WEJLvP3JrEG6E5GRuIHt5wpMwHGERtHe4Wm2CIvtf5gTBgr2tGOHKh5NdKEAFS2VkOPE91g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.2.0': + resolution: {integrity: sha512-+5suHwRiKGmhwyUaNT8a5QbrBvLFh2DbO910TEmGRH1aSxwrCezodvGQnulv4uiWEIv1Kq4ypRsJ5+O+ry1DiA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@rolldown/binding-win32-arm64-msvc@1.2.4': resolution: {integrity: sha512-AWLi0uBRYh6QlE7OKhiz+phZC0qwtij2QZmhmOdsLdFn64m7oMpooE9ICE3lhm9xMb4SpDo2WbHcxX1iFLFtqw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] + '@rolldown/binding-win32-x64-msvc@1.2.0': + resolution: {integrity: sha512-WfFv6/qGufotqBSBzBYwgpCkJBk8Nj7697LL9vTz/XWc67e0r3oewu8iMRwQj3AUL45GVD7wVsPjCsAAtW66Wg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@rolldown/binding-win32-x64-msvc@1.2.4': resolution: {integrity: sha512-UwSDJOg3dqCAejWdxclJjCsh3Qq4vLYMDxmyHqo1btz3stK2VqgwNd3mm5tuIwzSlGIQ/1H9Hr+Zn09mrezNqQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6743,277 +7511,139 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.59.0': - resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} - cpu: [arm] - os: [android] - '@rollup/rollup-android-arm-eabi@4.60.1': resolution: {integrity: sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.59.0': - resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} - cpu: [arm64] - os: [android] - '@rollup/rollup-android-arm64@4.60.1': resolution: {integrity: sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.59.0': - resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} - cpu: [arm64] - os: [darwin] - '@rollup/rollup-darwin-arm64@4.60.1': resolution: {integrity: sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.59.0': - resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} - cpu: [x64] - os: [darwin] - '@rollup/rollup-darwin-x64@4.60.1': resolution: {integrity: sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.59.0': - resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} - cpu: [arm64] - os: [freebsd] - '@rollup/rollup-freebsd-arm64@4.60.1': resolution: {integrity: sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.59.0': - resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} - cpu: [x64] - os: [freebsd] - '@rollup/rollup-freebsd-x64@4.60.1': resolution: {integrity: sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} - cpu: [arm] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-arm-gnueabihf@4.60.1': resolution: {integrity: sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==} cpu: [arm] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.59.0': - resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} - cpu: [arm] - os: [linux] - libc: [musl] - '@rollup/rollup-linux-arm-musleabihf@4.60.1': resolution: {integrity: sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==} cpu: [arm] os: [linux] libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.59.0': - resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} - cpu: [arm64] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-arm64-gnu@4.60.1': resolution: {integrity: sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.59.0': - resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} - cpu: [arm64] - os: [linux] - libc: [musl] - '@rollup/rollup-linux-arm64-musl@4.60.1': resolution: {integrity: sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.59.0': - resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} - cpu: [loong64] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-loong64-gnu@4.60.1': resolution: {integrity: sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==} cpu: [loong64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-loong64-musl@4.59.0': - resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} - cpu: [loong64] - os: [linux] - libc: [musl] - '@rollup/rollup-linux-loong64-musl@4.60.1': resolution: {integrity: sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==} cpu: [loong64] os: [linux] libc: [musl] - '@rollup/rollup-linux-ppc64-gnu@4.59.0': - resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-ppc64-gnu@4.60.1': resolution: {integrity: sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-musl@4.59.0': - resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} - cpu: [ppc64] - os: [linux] - libc: [musl] - '@rollup/rollup-linux-ppc64-musl@4.60.1': resolution: {integrity: sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==} cpu: [ppc64] os: [linux] libc: [musl] - '@rollup/rollup-linux-riscv64-gnu@4.59.0': - resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-riscv64-gnu@4.60.1': resolution: {integrity: sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==} cpu: [riscv64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.59.0': - resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} - cpu: [riscv64] - os: [linux] - libc: [musl] - '@rollup/rollup-linux-riscv64-musl@4.60.1': resolution: {integrity: sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==} cpu: [riscv64] os: [linux] libc: [musl] - '@rollup/rollup-linux-s390x-gnu@4.59.0': - resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} - cpu: [s390x] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-s390x-gnu@4.60.1': resolution: {integrity: sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.59.0': - resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} - cpu: [x64] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.60.1': resolution: {integrity: sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.59.0': - resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} - cpu: [x64] - os: [linux] - libc: [musl] - '@rollup/rollup-linux-x64-musl@4.60.1': resolution: {integrity: sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.59.0': - resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} - cpu: [x64] - os: [openbsd] - '@rollup/rollup-openbsd-x64@4.60.1': resolution: {integrity: sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.59.0': - resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} - cpu: [arm64] - os: [openharmony] - '@rollup/rollup-openharmony-arm64@4.60.1': resolution: {integrity: sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.59.0': - resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} - cpu: [arm64] - os: [win32] - '@rollup/rollup-win32-arm64-msvc@4.60.1': resolution: {integrity: sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.59.0': - resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} - cpu: [ia32] - os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.60.1': resolution: {integrity: sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.59.0': - resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} - cpu: [x64] - os: [win32] - '@rollup/rollup-win32-x64-gnu@4.60.1': resolution: {integrity: sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.59.0': - resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} - cpu: [x64] - os: [win32] - '@rollup/rollup-win32-x64-msvc@4.60.1': resolution: {integrity: sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==} cpu: [x64] @@ -7041,9 +7671,9 @@ packages: '@rushstack/ts-command-line@4.22.6': resolution: {integrity: sha512-QSRqHT/IfoC5nk9zn6+fgyqOPXHME0BfchII9EUPR19pocsNp/xSbeBCbD3PIR2Lg+Q5qk7OFqk1VhWPMdKHJg==} - '@schematics/angular@20.3.22': - resolution: {integrity: sha512-wXTdFaPIBnSSNj/m0kclvPCYQOc2EGTQN1+Q3j9RIghS9gKgPxI1unSfgieJldZWKzcl8+WdB2zUuDzE7tEshQ==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@schematics/angular@22.1.8': + resolution: {integrity: sha512-V37T9uHOQVHyxxOqwcJ9xjSIW/mW9UuSfjOc7WJE4V8+3zj0abDJLHuoxDZKe0icYGapgOcvHyYjtNOjSeSivw==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} '@segment/loosely-validate-event@2.0.0': resolution: {integrity: sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw==} @@ -7087,30 +7717,6 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - '@sigstore/bundle@4.0.0': - resolution: {integrity: sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A==} - engines: {node: ^20.17.0 || >=22.9.0} - - '@sigstore/core@3.2.0': - resolution: {integrity: sha512-kxHrDQ9YgfrWUSXU0cjsQGv8JykOFZQ9ErNKbFPWzk3Hgpwu8x2hHrQ9IdA8yl+j9RTLTC3sAF3Tdq1IQCP4oA==} - engines: {node: ^20.17.0 || >=22.9.0} - - '@sigstore/protobuf-specs@0.5.0': - resolution: {integrity: sha512-MM8XIwUjN2bwvCg1QvrMtbBmpcSHrkhFSCu1D11NyPvDQ25HEc4oG5/OcQfd/Tlf/OxmKWERDj0zGE23jQaMwA==} - engines: {node: ^18.17.0 || >=20.5.0} - - '@sigstore/sign@4.1.1': - resolution: {integrity: sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ==} - engines: {node: ^20.17.0 || >=22.9.0} - - '@sigstore/tuf@4.0.2': - resolution: {integrity: sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ==} - engines: {node: ^20.17.0 || >=22.9.0} - - '@sigstore/verify@3.1.0': - resolution: {integrity: sha512-mNe0Iigql08YupSOGv197YdHpPPr+EzDZmfCgMc7RPNaZTw5aLN01nBl6CHJOh3BGtnMIj83EeN4butBchc8Ag==} - engines: {node: ^20.17.0 || >=22.9.0} - '@sinclair/typebox@0.27.10': resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} @@ -7544,17 +8150,12 @@ packages: vitest: optional: true + '@ts-morph/common@0.22.0': + resolution: {integrity: sha512-HqNBuV/oIlMKdkLshXd1zKBqNQCsuPEsgQOkfFQ/eUKjRlwndXW1AjN9LVkBEIukm00gGXSRmfkl0Wv5VXLnlw==} + '@tsconfig/svelte@5.0.8': resolution: {integrity: sha512-UkNnw1/oFEfecR8ypyHIQuWYdkPvHiwcQ78sh+ymIiYoF+uc5H1UBetbjyqT+vgGJ3qQN6nhucJviX6HesWtKQ==} - '@tufjs/canonical-json@2.0.0': - resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==} - engines: {node: ^16.14.0 || >=18.0.0} - - '@tufjs/models@4.1.0': - resolution: {integrity: sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww==} - engines: {node: ^20.17.0 || >=22.9.0} - '@tybys/wasm-util@0.10.3': resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} @@ -7579,12 +8180,18 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/body-parser@1.19.6': + resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} + '@types/braces@3.0.5': resolution: {integrity: sha512-SQFof9H+LXeWNz8wDe7oN5zu7ket0qwMu5vZubW4GCJ8Kkeh6nBWUz87+KTz/G3Kqsrp0j/W253XJb3KMEeg3w==} '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} @@ -7606,6 +8213,15 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/express-serve-static-core@5.1.1': + resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==} + + '@types/express@5.0.6': + resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} + + '@types/gensync@1.0.5': + resolution: {integrity: sha512-MbsRCT7mTikHwKZ0X+LVUTLRrZZRLipTuXEO9qOYO+zmjMVk81axyClMROf6uoPD9MRVu46bx8zoR0Ad9q3NAg==} + '@types/graceful-fs@4.1.9': resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} @@ -7621,6 +8237,9 @@ packages: '@types/html-minifier-terser@6.1.0': resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} + '@types/http-errors@2.0.5': + resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} + '@types/istanbul-lib-coverage@2.0.6': resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} @@ -7633,6 +8252,9 @@ packages: '@types/jscodeshift@17.3.0': resolution: {integrity: sha512-ogvGG8VQQqAQQ096uRh+d6tBHrYuZjsumHirKtvBa5qEyTMN3IQJ7apo+sw9lxaB/iKWIhbbLlF3zmAWk9XQIg==} + '@types/jsesc@2.5.1': + resolution: {integrity: sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -7657,6 +8279,12 @@ packages: '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + '@types/qs@6.15.1': + resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: @@ -7668,6 +8296,12 @@ packages: '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + '@types/send@1.2.1': + resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} + + '@types/serve-static@2.2.0': + resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} + '@types/sort-by@1.2.3': resolution: {integrity: sha512-Q8Pg7o2iHWFf7pR4jIGb+ntxwwL7a/WWLFNJj8jEN14tPQdfwZLCqK68q6mo1WONqa68OysEPuFvNA3uGm0crw==} @@ -8070,8 +8704,8 @@ packages: peerDependencies: vinxi: ^0.5.5 - '@vitejs/plugin-basic-ssl@2.1.0': - resolution: {integrity: sha512-dOxxrhgyDIEUADhb/8OlV9JIqYLgos03YorAueTIeOUskLJSEsfwCByjbu98ctXitUN3znXKp0bYD/WHSudCeA==} + '@vitejs/plugin-basic-ssl@2.3.0': + resolution: {integrity: sha512-bdyo8rB3NnQbikdMpHaML9Z1OZPBu6fFOBo+OtxsBlvMJtysWskmBcnbIDhUqgC8tcxNv/a+BcV5U+2nQMm1OQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} peerDependencies: vite: ^6.4.1 @@ -8543,10 +9177,6 @@ packages: resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==} engines: {node: ^18.17.0 || >=20.5.0} - abbrev@4.0.0: - resolution: {integrity: sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==} - engines: {node: ^20.17.0 || >=22.9.0} - abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -8598,6 +9228,10 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} + agent-base@9.0.0: + resolution: {integrity: sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==} + engines: {node: '>= 20'} + aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} @@ -8657,9 +9291,8 @@ packages: ajv@8.18.0: resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} - algoliasearch@5.35.0: - resolution: {integrity: sha512-Y+moNhsqgLmvJdgTsO4GZNgsaDWv8AOGAaPeIeHKlDn/XunoAqYbA+XNpBd1dW8GOXAUDyxC9Rxc7AV4kpFcIg==} - engines: {node: '>= 14.0.0'} + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} alien-signals@1.0.13: resolution: {integrity: sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==} @@ -9092,9 +9725,9 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - beasties@0.3.5: - resolution: {integrity: sha512-NaWu+f4YrJxEttJSm16AzMIFtVldCvaJ68b1L098KpqXmxt9xOLtKoLkKxb8ekhOrLqEJAbvT6n6SEvB/sac7A==} - engines: {node: '>=14.0.0'} + beasties@0.4.3: + resolution: {integrity: sha512-fIIeLOcbAB/K1kb1HBVJoiq1alHL4RCYBSo5e7HzrNkkgMggXR1Vqt/Z9JWnkfe/qdCo66Ux3QRwZioAIBdWRA==} + engines: {node: '>=18.0.0'} better-opn@3.0.2: resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} @@ -9275,10 +9908,6 @@ packages: resolution: {integrity: sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==} engines: {node: ^16.14.0 || >=18.0.0} - cacache@20.0.4: - resolution: {integrity: sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA==} - engines: {node: ^20.17.0 || >=22.9.0} - cache-base@1.0.1: resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} engines: {node: '>=0.10.0'} @@ -9479,13 +10108,17 @@ packages: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} + cli-spinners@3.4.0: + resolution: {integrity: sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==} + engines: {node: '>=18.20'} + cli-table3@0.6.5: resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} - cli-truncate@4.0.0: - resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} - engines: {node: '>=18'} + cli-truncate@6.1.1: + resolution: {integrity: sha512-06p9vyLahLa4zkGcgsGxU6iEkSOiuI4fhCH6Emhe2lPAcoUv73n72DnODsnHA+5wwXGnV0n9M9/qOQJSjYhFhw==} + engines: {node: '>=22'} cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} @@ -9525,6 +10158,9 @@ packages: resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} engines: {node: '>=0.10.0'} + code-block-writer@12.0.0: + resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==} + collection-visit@1.0.0: resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} engines: {node: '>=0.10.0'} @@ -10285,14 +10921,14 @@ packages: resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} engines: {node: '>=0.12'} + entities@8.1.0: + resolution: {integrity: sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==} + engines: {node: '>=20.19.0'} + env-editor@0.4.2: resolution: {integrity: sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==} engines: {node: '>=8'} - env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - env-paths@4.0.0: resolution: {integrity: sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw==} engines: {node: '>=20'} @@ -10306,9 +10942,6 @@ packages: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} engines: {node: '>=18'} - err-code@2.0.3: - resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - errno@0.1.8: resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} hasBin: true @@ -10803,9 +11436,18 @@ packages: fast-loops@1.1.4: resolution: {integrity: sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg==} + fast-string-truncated-width@3.0.3: + resolution: {integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==} + + fast-string-width@3.0.2: + resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} + fast-uri@3.1.0: resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-wrap-ansi@0.2.2: + resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} + fastest-levenshtein@1.0.16: resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} engines: {node: '>= 4.9.1'} @@ -11365,6 +12007,10 @@ packages: hookable@6.1.1: resolution: {integrity: sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==} + hosted-git-info@10.1.1: + resolution: {integrity: sha512-DeOnSPAvOndYKfw075gt8yZzQ7S2hNztw34zBTfhIzLhmBTswIBg5/y+pqu/VD5cYWm5goAFTusDmUEmKZ0PEQ==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -11372,10 +12018,6 @@ packages: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} - hosted-git-info@9.0.2: - resolution: {integrity: sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==} - engines: {node: ^20.17.0 || >=22.9.0} - html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} @@ -11462,6 +12104,10 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} + https-proxy-agent@9.1.0: + resolution: {integrity: sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==} + engines: {node: '>= 20'} + httpxy@0.3.1: resolution: {integrity: sha512-XjG/CEoofEisMrnFr0D6U6xOZ4mRfnwcYQ9qvvnT4lvnX8BoeA3x3WofB75D+vZwpaobFVkBIHrZzoK40w8XSw==} @@ -11497,10 +12143,6 @@ packages: iferr@0.1.5: resolution: {integrity: sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==} - ignore-walk@8.0.0: - resolution: {integrity: sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A==} - engines: {node: ^20.17.0 || >=22.9.0} - ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -11572,10 +12214,6 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - ini@5.0.0: - resolution: {integrity: sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==} - engines: {node: ^18.17.0 || >=20.5.0} - ini@6.0.0: resolution: {integrity: sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==} engines: {node: ^20.17.0 || >=22.9.0} @@ -11716,10 +12354,6 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-fullwidth-code-point@4.0.0: - resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} - engines: {node: '>=12'} - is-fullwidth-code-point@5.1.0: resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} engines: {node: '>=18'} @@ -11861,10 +12495,6 @@ packages: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} - is-unicode-supported@1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} - is-unicode-supported@2.1.0: resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} engines: {node: '>=18'} @@ -11922,10 +12552,6 @@ packages: resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==} engines: {node: '>=18'} - isexe@4.0.0: - resolution: {integrity: sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==} - engines: {node: '>=20'} - isobject@2.1.0: resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} engines: {node: '>=0.10.0'} @@ -12061,6 +12687,9 @@ packages: jose@6.2.2: resolution: {integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==} + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -12136,10 +12765,6 @@ packages: json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-parse-even-better-errors@5.0.0: - resolution: {integrity: sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==} - engines: {node: ^20.17.0 || >=22.9.0} - json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -12176,10 +12801,6 @@ packages: jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -12411,9 +13032,9 @@ packages: resolution: {integrity: sha512-I8oW2+QL5KJo8zXNWX046M134WchxsXC7SawLPvRQpogCbkyQIaFxPE89A2HiwR7vAK2Dm2ERBAmyjTYGYEpBg==} hasBin: true - listr2@9.0.1: - resolution: {integrity: sha512-SL0JY3DaxylDuo/MecFeiC+7pedM0zia33zl0vcjgwcq1q1FWWF1To9EIauPbl8GbMCU0R2e0uJ8bZunhYKD2g==} - engines: {node: '>=20.0.0'} + listr2@11.0.0: + resolution: {integrity: sha512-8K88S0aSrcSXdJfiZtEy5BQMnR+TyjrCGLcgAvQs6ta0NEnIm0RJ72/Pv67Jvg07cfBhDbuN74V81lSSVYEFEw==} + engines: {node: '>=22.13.0'} lit-element@4.2.2: resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} @@ -12424,8 +13045,8 @@ packages: lit@3.3.2: resolution: {integrity: sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==} - lmdb@3.4.2: - resolution: {integrity: sha512-nwVGUfTBUwJKXd6lRV8pFNfnrCC1+l49ESJRM19t/tFb/97QfJEixe5DYRvug5JO7DSFKoKaVy7oGMt5rVqZvg==} + lmdb@3.5.6: + resolution: {integrity: sha512-j3uE8ReKNyUWDjhfEFSJqE/1DLtfTR5Z8yFzVHvBjAk37wNg7HdScjcv8ttPHRvrdgPQMPWxFFI0SsdBzI5lBw==} hasBin: true loader-runner@2.4.0: @@ -12506,13 +13127,13 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} - log-symbols@6.0.0: - resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + log-symbols@7.0.1: + resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==} engines: {node: '>=18'} - log-update@6.1.0: - resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} - engines: {node: '>=18'} + log-update@8.0.0: + resolution: {integrity: sha512-lddSgOt3bPASrylL54ZSpy8nBHns+vBVSoILlVOx+dei300pnLRN958rj/EdlVLKuWlSESU3qdnDZdAI7FXYGg==} + engines: {node: '>=22'} longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -12545,12 +13166,12 @@ packages: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true - magic-string@0.30.17: - resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} - magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magic-string@1.0.0: + resolution: {integrity: sha512-CGvjzMN08iv6w1mm4/x3Gh1hLb4VnyRUA15FFpl6CsCIGGoe36k7kY5KNz9QDbSBN5I/fWHM6ZlIkUTa5xdUEA==} + magicast@0.2.11: resolution: {integrity: sha512-6saXbRDA1HMkqbsvHOU6HBjCVgZT460qheRkLhJQHWAbhXoWESI3Kn/dGGXyKs15FFKR85jsUqFx2sMK0wy/5g==} @@ -12572,10 +13193,6 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - make-fetch-happen@15.0.5: - resolution: {integrity: sha512-uCbIa8jWWmQZt4dSnEStkVC6gdakiinAm4PiGsywIkguF0eWMdcjDz0ECYhUolFU3pFLOev9VNPCEygydXnddg==} - engines: {node: ^20.17.0 || >=22.9.0} - makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} @@ -12967,10 +13584,6 @@ packages: resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} engines: {node: '>=16 || 14 >=14.17'} - minipass-fetch@5.0.2: - resolution: {integrity: sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ==} - engines: {node: ^20.17.0 || >=22.9.0} - minipass-flush@1.0.7: resolution: {integrity: sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==} engines: {node: '>= 8'} @@ -12979,10 +13592,6 @@ packages: resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} engines: {node: '>=8'} - minipass-sized@2.0.0: - resolution: {integrity: sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA==} - engines: {node: '>=8'} - minipass@3.3.6: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} @@ -13020,6 +13629,11 @@ packages: engines: {node: '>=10'} hasBin: true + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + mlly@1.8.2: resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} @@ -13065,6 +13679,10 @@ packages: resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} engines: {node: ^18.17.0 || >=20.5.0} + mute-stream@3.0.0: + resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} + engines: {node: ^20.17.0 || >=22.9.0} + mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -13248,11 +13866,6 @@ packages: resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true - node-gyp@12.2.0: - resolution: {integrity: sha512-q23WdzrQv48KozXlr0U1v9dwO/k59NHeSzn6loGcasyf0UnSrtzs8kRxM+mfwJSf0DkX0s43hcqgnSO4/VNthQ==} - engines: {node: ^20.17.0 || >=22.9.0} - hasBin: true - node-html-parser@6.1.13: resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==} @@ -13276,11 +13889,6 @@ packages: engines: {node: ^18.17.0 || >=20.5.0} hasBin: true - nopt@9.0.0: - resolution: {integrity: sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==} - engines: {node: ^20.17.0 || >=22.9.0} - hasBin: true - normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -13288,37 +13896,13 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - npm-bundled@5.0.0: - resolution: {integrity: sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==} - engines: {node: ^20.17.0 || >=22.9.0} - - npm-install-checks@8.0.0: - resolution: {integrity: sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==} - engines: {node: ^20.17.0 || >=22.9.0} - - npm-normalize-package-bin@5.0.0: - resolution: {integrity: sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==} - engines: {node: ^20.17.0 || >=22.9.0} - npm-package-arg@11.0.3: resolution: {integrity: sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==} engines: {node: ^16.14.0 || >=18.0.0} - npm-package-arg@13.0.0: - resolution: {integrity: sha512-+t2etZAGcB7TbbLHfDwooV9ppB2LhhcT6A+L9cahsf9mEUAoQ6CktLEVvEnpD0N5CkX7zJqnPGaFtoQDy9EkHQ==} - engines: {node: ^20.17.0 || >=22.9.0} - - npm-packlist@10.0.4: - resolution: {integrity: sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng==} - engines: {node: ^20.17.0 || >=22.9.0} - - npm-pick-manifest@11.0.3: - resolution: {integrity: sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==} - engines: {node: ^20.17.0 || >=22.9.0} - - npm-registry-fetch@19.1.1: - resolution: {integrity: sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw==} - engines: {node: ^20.17.0 || >=22.9.0} + npm-package-arg@14.0.0: + resolution: {integrity: sha512-69XQh3k+dtGa1p+7RaR57IuG3rCko96xr/nUfN4yDYBXbTYICiWcOpsFKLN2GtGE9cyIljE+f1exnaYt9MvM+Q==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} npm-run-all2@5.0.2: resolution: {integrity: sha512-S2G6FWZ3pNWAAKm2PFSOtEAG/N+XO/kz3+9l6V91IY+Y3XFSt7Lp7DV92KCgEboEW0hRTu0vFaMe4zXDZYaOyA==} @@ -13501,9 +14085,9 @@ packages: resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} engines: {node: '>=10'} - ora@8.2.0: - resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} - engines: {node: '>=18'} + ora@9.4.1: + resolution: {integrity: sha512-6VlU9MLXbjVQD04AZCMX28hVtA5bUoadvUqO76MUCVA0ilwJbMiHsITRPfyVm6p/BC0Av/BXMujx39WCe1LEqw==} + engines: {node: '>=20'} ordered-binary@1.6.1: resolution: {integrity: sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==} @@ -13521,6 +14105,14 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} + oxc-parser@0.121.0: + resolution: {integrity: sha512-ek9o58+SCv6AV7nchiAcUJy1DNE2CC5WRdBcO0mF+W4oRjNQfPO7b3pLjTHSFECpHkKGOZSQxx3hk8viIL5YCg==} + engines: {node: ^20.19.0 || >=22.12.0} + + oxc-parser@0.142.0: + resolution: {integrity: sha512-kKR+jPiRJYJDexVoziIg/FVGvr1fT1FZSSJOk6tVoMKKSlsf1Cso+cgGCJkOEDWOP174vRntCPFKg+AS7InWvw==} + engines: {node: ^20.19.0 || >=22.12.0} + oxc-parser@0.143.0: resolution: {integrity: sha512-ov0NzaDCOInknS7mP1cwKdJERt3utPW8ldjtdUXQ8Ty0GEFD08wk422vCUN0d7pST6kqtV7dxoI9w1Zi0l/9TA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -13592,10 +14184,6 @@ packages: resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==} engines: {node: '>=16'} - p-map@7.0.4: - resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} - engines: {node: '>=18'} - p-queue@6.6.2: resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} engines: {node: '>=8'} @@ -13629,11 +14217,6 @@ packages: package-manager-detector@1.6.0: resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} - pacote@21.0.4: - resolution: {integrity: sha512-RplP/pDW0NNNDh3pnaoIWYPvNenS7UqMbXyvMqJczosiFWTeGGwJC2NQBLqKf4rGLFfwCOnntw1aEp9Jiqm1MA==} - engines: {node: ^20.17.0 || >=22.9.0} - hasBin: true - pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -13676,8 +14259,8 @@ packages: parse-statements@1.0.11: resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==} - parse5-html-rewriting-stream@8.0.0: - resolution: {integrity: sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==} + parse5-html-rewriting-stream@8.0.1: + resolution: {integrity: sha512-NaRku2aMpUN1Sh1Gyk1KWUh2A7EJx2c6qYzvwsPtqhoHoaURshdrceYK3LunVCm3WHhm6FS7Vcczbvdh3/UIVw==} parse5-htmlparser2-tree-adapter@6.0.1: resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} @@ -13802,10 +14385,6 @@ packages: resolution: {integrity: sha512-cfDHL6LStTEKlNilboNtobT/kEa30PtAf2Q1OgszfrG/rpVl1xaFWT9ktfkS306GmHgmnad1Sw4wabhlvFtsTw==} engines: {node: '>=10'} - picomatch@4.0.4: - resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} - engines: {node: '>=12'} - picomatch@4.0.5: resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} @@ -13827,8 +14406,8 @@ packages: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} - piscina@5.1.3: - resolution: {integrity: sha512-0u3N7H4+hbr40KjuVn2uNhOcthu/9usKhnw5vT3J7ply79v3D3M8naI00el9Klcy16x557VsEkkUQaHCWFXC/g==} + piscina@5.2.0: + resolution: {integrity: sha512-DszUCKeVN/5G5QKo6jAVHL8fmKnkJvQ0ACiVgY7YGCq3TUB2oznAOayvZPIAdEThvhczkXR+qm3IHsNXpFCYfA==} engines: {node: '>=20.x'} pkce-challenge@5.0.1: @@ -14038,13 +14617,9 @@ packages: resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - proc-log@5.0.0: - resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==} - engines: {node: ^18.17.0 || >=20.5.0} - - proc-log@6.1.0: - resolution: {integrity: sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==} - engines: {node: ^20.17.0 || >=22.9.0} + proc-log@7.0.0: + resolution: {integrity: sha512-FYgfaA69XZ93zaXLoMNQ+ViDXGGBgR8aLh03txzcFhV+9xOXx7+8DLCULrKKpR9+GsH9ZfHm82aSUPpozX0Ztg==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -14065,10 +14640,6 @@ packages: bluebird: optional: true - promise-retry@2.0.1: - resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} - engines: {node: '>=10'} - promise@7.3.1: resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} @@ -14089,6 +14660,15 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + proxy-agent-negotiate@1.1.0: + resolution: {integrity: sha512-N8IBcM3UgCVzz2L2Lqv8DVntDnnC8/hiV4nEDUPkqq72TPUgYWjQc+bdZlBPZK9LzPAvOY//gAt0S0DApoOXWQ==} + engines: {node: '>= 20'} + peerDependencies: + kerberos: ^2.0.0 + peerDependenciesMeta: + kerberos: + optional: true + proxy-from-env@2.1.0: resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} engines: {node: '>=10'} @@ -14549,11 +15129,6 @@ packages: resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} engines: {node: '>=10'} - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} - engines: {node: '>= 0.4'} - hasBin: true - resolve@1.22.11: resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} @@ -14595,10 +15170,6 @@ packages: retext@9.0.0: resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} - retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - rettime@0.10.1: resolution: {integrity: sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw==} @@ -14606,9 +15177,6 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rimraf@2.6.3: resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -14647,6 +15215,11 @@ packages: vue-tsc: optional: true + rolldown@1.2.0: + resolution: {integrity: sha512-u7tgm5l4Yw1iTqUL4EcYOAt7fFvCgQMLeidrnD4GALlC6aOznCjezYajgxeyKw27u0Q5N7fwgCzjVyPIWzwuBA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + rolldown@1.2.4: resolution: {integrity: sha512-rSr7irW0K7QRWzjdJXqZowkcRdDtjRduh43rBltnVKd0VFq839l1lJoDvGJb6gl7+4rTTCrPWu+YfujUL8Ug7w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -14670,11 +15243,6 @@ packages: rollup: optional: true - rollup@4.59.0: - resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - rollup@4.60.1: resolution: {integrity: sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -14738,9 +15306,9 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - sass@1.90.0: - resolution: {integrity: sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==} - engines: {node: '>=14.0.0'} + sass@1.101.0: + resolution: {integrity: sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw==} + engines: {node: '>=20.19.0'} hasBin: true sax@1.6.0: @@ -14792,13 +15360,13 @@ packages: engines: {node: '>=10'} hasBin: true - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} engines: {node: '>=10'} hasBin: true - semver@7.7.4: - resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} engines: {node: '>=10'} hasBin: true @@ -14979,10 +15547,6 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - sigstore@4.1.0: - resolution: {integrity: sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==} - engines: {node: ^20.17.0 || >=22.9.0} - simple-code-frame@1.3.0: resolution: {integrity: sha512-MB4pQmETUBlNs62BBeRjIFGeuy/x6gGKh7+eRUemn1rCFhqo7K+4slPqsyizCbcbYLnaYqaoZ2FWsZ/jN06D8w==} @@ -15025,22 +15589,14 @@ packages: resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} engines: {node: '>=14.16'} - slice-ansi@5.0.0: - resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} - engines: {node: '>=12'} - - slice-ansi@7.1.2: - resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} - engines: {node: '>=18'} + slice-ansi@9.0.0: + resolution: {integrity: sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==} + engines: {node: '>=22'} slugify@1.6.8: resolution: {integrity: sha512-HVk9X1E0gz3mSpoi60h/saazLKXKaZThMLU3u/aNwoYn8/xQyX2MGxL0ui2eaokkD7tF+Zo+cKTHUbe1mmmGzA==} engines: {node: '>=8.0.0'} - smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - smob@1.6.1: resolution: {integrity: sha512-KAkBqZl3c2GvNgNhcoyJae1aKldDW0LO279wF9bk1PnluRTETKBq0WyzRXxEhoQLk56yHaOY4JCBEKDuJIET5g==} engines: {node: '>=20.0.0'} @@ -15061,14 +15617,6 @@ packages: resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} engines: {node: '>=0.10.0'} - socks-proxy-agent@8.0.5: - resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} - engines: {node: '>= 14'} - - socks@2.8.7: - resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - solid-js@1.9.12: resolution: {integrity: sha512-QzKaSJq2/iDrWR1As6MHZQ8fQkdOBf8GReYb7L5iKwMGceg7HxDcaOHk0at66tNgn9U2U7dXo8ZZpLIAmGMzgw==} @@ -15173,10 +15721,6 @@ packages: resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ssri@13.0.1: - resolution: {integrity: sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ==} - engines: {node: ^20.17.0 || >=22.9.0} - ssri@6.0.2: resolution: {integrity: sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==} @@ -15223,8 +15767,8 @@ packages: std-env@4.0.0: resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==} - stdin-discarder@0.2.2: - resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + stdin-discarder@0.3.2: + resolution: {integrity: sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A==} engines: {node: '>=18'} stop-iteration-iterator@1.1.0: @@ -15280,6 +15824,10 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string-width@8.2.2: + resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==} + engines: {node: '>=20'} + string.prototype.matchall@4.0.12: resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} engines: {node: '>= 0.4'} @@ -15610,10 +16158,6 @@ packages: resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} engines: {node: '>=18'} - tinyglobby@0.2.14: - resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} - engines: {node: '>=12.0.0'} - tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} @@ -15720,6 +16264,9 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + ts-morph@21.0.1: + resolution: {integrity: sha512-dbDtVdEAncKctzrVZ+Nr7kHpHkv+0JDJb2MjjpBaj8bFeCkePU9rHfMklmhuLFnpeq/EJZk2IhStY6NzqgjOkg==} + ts-pattern@5.9.0: resolution: {integrity: sha512-6s5V71mX8qBUmlgbrfL33xDUwO0fq48rxAu2LBE11WBeGdpCPOsXksQbZJHvHwhrd3QjUusd3mAOM5Gg0mFBLg==} @@ -15783,10 +16330,6 @@ packages: tty-browserify@0.0.0: resolution: {integrity: sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==} - tuf-js@4.1.0: - resolution: {integrity: sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ==} - engines: {node: ^20.17.0 || >=22.9.0} - tupleson@0.23.1: resolution: {integrity: sha512-+vPs/gj7nue5pq78/bi58sa0SohFgjXg49T6YMyWav+0xUz29rhlSXXZJBfdv8BXacG1IOqQaIOaGGHVoPTiWg==} engines: {node: '>=18'} @@ -16276,9 +16819,9 @@ packages: resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - validate-npm-package-name@6.0.2: - resolution: {integrity: sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==} - engines: {node: ^18.17.0 || >=20.5.0} + validate-npm-package-name@8.0.0: + resolution: {integrity: sha512-SCv6OOV6Xj2/3cXy3dGmADluJTNcL3o7hZAglNPTe+WYuEuvxgJzxPrSDLZhF+CwyQOubqgecjMmTJGMVLWjYQ==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} @@ -16384,6 +16927,46 @@ packages: yaml: optional: true + vite@7.1.11: + resolution: {integrity: sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^22.15.3 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + vitefu@1.1.3: resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==} peerDependencies: @@ -16584,12 +17167,8 @@ packages: watchpack@1.7.5: resolution: {integrity: sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==} - watchpack@2.4.4: - resolution: {integrity: sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==} - engines: {node: '>=10.13.0'} - - watchpack@2.5.1: - resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} + watchpack@2.5.2: + resolution: {integrity: sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==} engines: {node: '>=10.13.0'} wcwidth@1.0.1: @@ -16759,11 +17338,6 @@ packages: engines: {node: ^16.13.0 || >=18.0.0} hasBin: true - which@6.0.1: - resolution: {integrity: sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==} - engines: {node: ^20.17.0 || >=22.9.0} - hasBin: true - why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} engines: {node: '>=8'} @@ -16786,6 +17360,10 @@ packages: worker-farm@1.7.0: resolution: {integrity: sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==} + wrap-ansi@10.0.1: + resolution: {integrity: sha512-M0N4xzyzosiIok3svYlEo1sdLZts/8FPgYH/GPC3wvlmPoRvnoManGMrE54waYj3tISA8w6lsdesfVv67qSr8Q==} + engines: {node: '>=20'} + wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -16863,6 +17441,10 @@ packages: resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} engines: {node: '>=12'} + xhr2@0.2.1: + resolution: {integrity: sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw==} + engines: {node: '>= 6'} + xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} @@ -16956,6 +17538,10 @@ packages: resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yargs@18.1.0: + resolution: {integrity: sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -17018,14 +17604,11 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.1.13: - resolution: {integrity: sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==} - zod@4.4.3: resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} - zone.js@0.15.0: - resolution: {integrity: sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA==} + zone.js@0.16.1: + resolution: {integrity: sha512-dpvY17vxYIW3+bNrP0ClUlaiY0CiIRK3tnoLaGoQsQcY9/I/NpzIWQ7tQNhbV7LacQMpCII6wVzuL3tuWOyfuA==} zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -17040,106 +17623,22 @@ snapshots: '@adobe/css-tools@4.4.4': {} - '@algolia/abtesting@1.1.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@algolia/requester-browser-xhr': 5.35.0 - '@algolia/requester-fetch': 5.35.0 - '@algolia/requester-node-http': 5.35.0 - - '@algolia/client-abtesting@5.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@algolia/requester-browser-xhr': 5.35.0 - '@algolia/requester-fetch': 5.35.0 - '@algolia/requester-node-http': 5.35.0 - - '@algolia/client-analytics@5.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@algolia/requester-browser-xhr': 5.35.0 - '@algolia/requester-fetch': 5.35.0 - '@algolia/requester-node-http': 5.35.0 - '@algolia/client-common@5.2.1': {} - '@algolia/client-common@5.35.0': {} - - '@algolia/client-insights@5.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@algolia/requester-browser-xhr': 5.35.0 - '@algolia/requester-fetch': 5.35.0 - '@algolia/requester-node-http': 5.35.0 - - '@algolia/client-personalization@5.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@algolia/requester-browser-xhr': 5.35.0 - '@algolia/requester-fetch': 5.35.0 - '@algolia/requester-node-http': 5.35.0 - - '@algolia/client-query-suggestions@5.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@algolia/requester-browser-xhr': 5.35.0 - '@algolia/requester-fetch': 5.35.0 - '@algolia/requester-node-http': 5.35.0 - '@algolia/client-search@5.2.1': dependencies: '@algolia/client-common': 5.2.1 '@algolia/requester-browser-xhr': 5.2.1 '@algolia/requester-node-http': 5.2.1 - '@algolia/client-search@5.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@algolia/requester-browser-xhr': 5.35.0 - '@algolia/requester-fetch': 5.35.0 - '@algolia/requester-node-http': 5.35.0 - - '@algolia/ingestion@1.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@algolia/requester-browser-xhr': 5.35.0 - '@algolia/requester-fetch': 5.35.0 - '@algolia/requester-node-http': 5.35.0 - - '@algolia/monitoring@1.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@algolia/requester-browser-xhr': 5.35.0 - '@algolia/requester-fetch': 5.35.0 - '@algolia/requester-node-http': 5.35.0 - - '@algolia/recommend@5.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@algolia/requester-browser-xhr': 5.35.0 - '@algolia/requester-fetch': 5.35.0 - '@algolia/requester-node-http': 5.35.0 - '@algolia/requester-browser-xhr@5.2.1': dependencies: '@algolia/client-common': 5.2.1 - '@algolia/requester-browser-xhr@5.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - - '@algolia/requester-fetch@5.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@algolia/requester-node-http@5.2.1': dependencies: '@algolia/client-common': 5.2.1 - '@algolia/requester-node-http@5.35.0': - dependencies: - '@algolia/client-common': 5.35.0 - '@alloc/quick-lru@5.2.0': {} '@ampproject/remapping@2.3.0': @@ -17147,84 +17646,226 @@ snapshots: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 + '@analogjs/vite-plugin-angular@2.5.2(@angular/build@22.1.8(4affaef227d0997be37379ba361cd6fd))(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + dependencies: + magic-string: 0.30.21 + obug: 2.1.4 + oxc-parser: 0.121.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + tinyglobby: 0.2.17 + ts-morph: 21.0.1 + optionalDependencies: + '@angular/build': 22.1.8(4affaef227d0997be37379ba361cd6fd) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + '@analogjs/vite-plugin-angular@2.5.2(@angular/build@22.1.8(e62ab7c722b8b89e816de2e21b02397f))(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + dependencies: + magic-string: 0.30.21 + obug: 2.1.4 + oxc-parser: 0.121.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + tinyglobby: 0.2.17 + ts-morph: 21.0.1 + optionalDependencies: + '@angular/build': 22.1.8(e62ab7c722b8b89e816de2e21b02397f) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + '@andrewbranch/untar.js@1.0.3': {} - '@angular-devkit/architect@0.2003.22(chokidar@5.0.0)': + '@angular-devkit/architect@0.2201.8(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 20.3.22(chokidar@5.0.0) + '@angular-devkit/core': 22.1.8(chokidar@5.0.0) rxjs: 7.8.2 transitivePeerDependencies: - chokidar - '@angular-devkit/core@20.3.22(chokidar@5.0.0)': + '@angular-devkit/core@22.1.8(chokidar@5.0.0)': dependencies: - ajv: 8.18.0 - ajv-formats: 3.0.1(ajv@8.18.0) + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) jsonc-parser: 3.3.1 - picomatch: 4.0.4 + picomatch: 4.0.5 rxjs: 7.8.2 source-map: 0.7.6 optionalDependencies: chokidar: 5.0.0 - '@angular-devkit/schematics@20.3.22(chokidar@5.0.0)': + '@angular-devkit/schematics@22.1.8(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 20.3.22(chokidar@5.0.0) + '@angular-devkit/core': 22.1.8(chokidar@5.0.0) jsonc-parser: 3.3.1 - magic-string: 0.30.17 - ora: 8.2.0 + magic-string: 1.0.0 + ora: 9.4.1 rxjs: 7.8.2 transitivePeerDependencies: - chokidar - '@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))': + '@angular/build@22.1.8(4affaef227d0997be37379ba361cd6fd)': dependencies: - '@angular/core': 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + '@ampproject/remapping': 2.3.0 + '@angular-devkit/architect': 0.2201.8(chokidar@5.0.0) + '@angular/compiler': 22.1.6 + '@angular/compiler-cli': 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) + '@babel/core': 8.0.1 + '@babel/helper-annotate-as-pure': 8.0.0 + '@babel/helper-split-export-declaration': 7.24.7 + '@inquirer/confirm': 6.1.1(@types/node@22.19.15) + '@vitejs/plugin-basic-ssl': 2.3.0(vite@7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + beasties: 0.4.3 + browserslist: 4.28.2 + esbuild: 0.27.4 + https-proxy-agent: 9.1.0 + jsonc-parser: 3.3.1 + listr2: 11.0.0 + magic-string: 1.0.0 + mrmime: 2.0.1 + oxc-parser: 0.142.0 + parse5-html-rewriting-stream: 8.0.1 + picomatch: 4.0.5 + piscina: 5.2.0 + rolldown: 1.2.0 + sass: 1.101.0 + semver: 7.8.5 + source-map-support: 0.5.21 + tinyglobby: 0.2.17 tslib: 2.8.1 + typescript: 6.0.3 + vite: 7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + watchpack: 2.5.2 + optionalDependencies: + '@angular/core': 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@angular/platform-server': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/compiler@22.1.6)(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@angular/ssr': 22.1.8(caf12b5b30d21bb6295944d46eee472d) + istanbul-lib-instrument: 6.0.3 + lmdb: 3.5.6 + postcss: 8.5.8 + rollup: 4.60.1 + tailwindcss: 4.2.2 + vitest: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + transitivePeerDependencies: + - '@types/node' + - chokidar + - jiti + - kerberos + - lightningcss + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml - '@angular/build@20.3.22(@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3))(@angular/compiler@20.3.18)(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@types/node@22.19.15)(chokidar@5.0.0)(jiti@2.7.0)(lightningcss@1.32.0)(postcss@8.5.8)(tailwindcss@4.2.2)(terser@5.46.1)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.8.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(yaml@2.9.0)': + '@angular/build@22.1.8(52d17f587f491aa5bd2e2175a98e7579)': dependencies: '@ampproject/remapping': 2.3.0 - '@angular-devkit/architect': 0.2003.22(chokidar@5.0.0) - '@angular/compiler': 20.3.18 - '@angular/compiler-cli': 20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3) - '@babel/core': 7.28.3 - '@babel/helper-annotate-as-pure': 7.27.3 + '@angular-devkit/architect': 0.2201.8(chokidar@5.0.0) + '@angular/compiler': 22.1.6 + '@angular/compiler-cli': 22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3) + '@babel/core': 8.0.1 + '@babel/helper-annotate-as-pure': 8.0.0 '@babel/helper-split-export-declaration': 7.24.7 - '@inquirer/confirm': 5.1.14(@types/node@22.19.15) - '@vitejs/plugin-basic-ssl': 2.1.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) - beasties: 0.3.5 + '@inquirer/confirm': 6.1.1(@types/node@22.19.15) + '@vitejs/plugin-basic-ssl': 2.3.0(vite@7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + beasties: 0.4.3 browserslist: 4.28.2 esbuild: 0.27.4 - https-proxy-agent: 7.0.6 + https-proxy-agent: 9.1.0 + jsonc-parser: 3.3.1 + listr2: 11.0.0 + magic-string: 1.0.0 + mrmime: 2.0.1 + oxc-parser: 0.142.0 + parse5-html-rewriting-stream: 8.0.1 + picomatch: 4.0.5 + piscina: 5.2.0 + rolldown: 1.2.0 + sass: 1.101.0 + semver: 7.8.5 + source-map-support: 0.5.21 + tinyglobby: 0.2.17 + tslib: 2.8.1 + typescript: 6.0.3 + vite: 7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + watchpack: 2.5.2 + optionalDependencies: + '@angular/core': 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@angular/platform-server': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/compiler@22.1.6)(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@angular/ssr': 22.1.8(caf12b5b30d21bb6295944d46eee472d) istanbul-lib-instrument: 6.0.3 + lmdb: 3.5.6 + postcss: 8.5.8 + rollup: 4.60.1 + tailwindcss: 4.2.2 + vitest: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + transitivePeerDependencies: + - '@types/node' + - chokidar + - jiti + - kerberos + - lightningcss + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + '@angular/build@22.1.8(e62ab7c722b8b89e816de2e21b02397f)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@angular-devkit/architect': 0.2201.8(chokidar@5.0.0) + '@angular/compiler': 22.1.6 + '@angular/compiler-cli': 22.1.6(@angular/compiler@22.1.6)(typescript@5.9.3) + '@babel/core': 8.0.1 + '@babel/helper-annotate-as-pure': 8.0.0 + '@babel/helper-split-export-declaration': 7.24.7 + '@inquirer/confirm': 6.1.1(@types/node@22.19.15) + '@vitejs/plugin-basic-ssl': 2.3.0(vite@7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + beasties: 0.4.3 + browserslist: 4.28.2 + esbuild: 0.27.4 + https-proxy-agent: 9.1.0 jsonc-parser: 3.3.1 - listr2: 9.0.1 - magic-string: 0.30.17 + listr2: 11.0.0 + magic-string: 1.0.0 mrmime: 2.0.1 - parse5-html-rewriting-stream: 8.0.0 - picomatch: 4.0.4 - piscina: 5.1.3 - rollup: 4.59.0 - sass: 1.90.0 - semver: 7.7.2 + oxc-parser: 0.142.0 + parse5-html-rewriting-stream: 8.0.1 + picomatch: 4.0.5 + piscina: 5.2.0 + rolldown: 1.2.0 + sass: 1.101.0 + semver: 7.8.5 source-map-support: 0.5.21 - tinyglobby: 0.2.14 + tinyglobby: 0.2.17 tslib: 2.8.1 - typescript: 5.8.3 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - watchpack: 2.4.4 + typescript: 5.9.3 + vite: 7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + watchpack: 2.5.2 optionalDependencies: - '@angular/core': 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/platform-browser': 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - lmdb: 3.4.2 + '@angular/core': 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@angular/platform-server': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/compiler@22.1.6)(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@angular/ssr': 22.1.8(caf12b5b30d21bb6295944d46eee472d) + istanbul-lib-instrument: 6.0.3 + lmdb: 3.5.6 postcss: 8.5.8 + rollup: 4.60.1 tailwindcss: 4.2.2 - vitest: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vitest: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) transitivePeerDependencies: - '@types/node' - chokidar - jiti + - kerberos - lightningcss - sass-embedded - stylus @@ -17234,42 +17875,38 @@ snapshots: - tsx - yaml - '@angular/cli@20.3.22(@types/node@22.19.15)(chokidar@5.0.0)': + '@angular/cli@22.1.8(@types/node@22.19.15)(chokidar@5.0.0)': dependencies: - '@angular-devkit/architect': 0.2003.22(chokidar@5.0.0) - '@angular-devkit/core': 20.3.22(chokidar@5.0.0) - '@angular-devkit/schematics': 20.3.22(chokidar@5.0.0) - '@inquirer/prompts': 7.8.2(@types/node@22.19.15) - '@listr2/prompt-adapter-inquirer': 3.0.1(@inquirer/prompts@7.8.2(@types/node@22.19.15))(@types/node@22.19.15)(listr2@9.0.1) - '@modelcontextprotocol/sdk': 1.26.0(zod@4.1.13) - '@schematics/angular': 20.3.22(chokidar@5.0.0) - '@yarnpkg/lockfile': 1.1.0 - algoliasearch: 5.35.0 - ini: 5.0.0 + '@angular-devkit/architect': 0.2201.8(chokidar@5.0.0) + '@angular-devkit/core': 22.1.8(chokidar@5.0.0) + '@angular-devkit/schematics': 22.1.8(chokidar@5.0.0) + '@inquirer/prompts': 8.5.2(@types/node@22.19.15) + '@listr2/prompt-adapter-inquirer': 4.2.5(@inquirer/prompts@8.5.2(@types/node@22.19.15))(@types/node@22.19.15)(listr2@11.0.0) + '@modelcontextprotocol/sdk': 1.30.0(zod@4.4.3) + '@schematics/angular': 22.1.8(chokidar@5.0.0) jsonc-parser: 3.3.1 - listr2: 9.0.1 - npm-package-arg: 13.0.0 - pacote: 21.0.4 - resolve: 1.22.10 - semver: 7.7.2 - yargs: 18.0.0 - zod: 4.1.13 + listr2: 11.0.0 + npm-package-arg: 14.0.0 + parse5-html-rewriting-stream: 8.0.1 + semver: 7.8.5 + yargs: 18.1.0 + zod: 4.4.3 transitivePeerDependencies: - '@cfworker/json-schema' - '@types/node' - chokidar - supports-color - '@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)': + '@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2)': dependencies: - '@angular/core': 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/core': 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/compiler-cli@20.3.18(@angular/compiler@20.3.18)(typescript@5.8.3)': + '@angular/compiler-cli@22.1.6(@angular/compiler@22.1.6)(typescript@5.9.3)': dependencies: - '@angular/compiler': 20.3.18 - '@babel/core': 7.28.3 + '@angular/compiler': 22.1.6 + '@babel/core': 8.0.1 '@jridgewell/sourcemap-codec': 1.5.5 chokidar: 5.0.0 convert-source-map: 1.9.0 @@ -17278,46 +17915,77 @@ snapshots: tslib: 2.8.1 yargs: 18.0.0 optionalDependencies: - typescript: 5.8.3 - transitivePeerDependencies: - - supports-color + typescript: 5.9.3 - '@angular/compiler@20.3.18': + '@angular/compiler-cli@22.1.6(@angular/compiler@22.1.6)(typescript@6.0.3)': dependencies: + '@angular/compiler': 22.1.6 + '@babel/core': 8.0.1 + '@jridgewell/sourcemap-codec': 1.5.5 + chokidar: 5.0.0 + convert-source-map: 1.9.0 + reflect-metadata: 0.2.2 + semver: 7.7.4 tslib: 2.8.1 + yargs: 18.0.0 + optionalDependencies: + typescript: 6.0.3 - '@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)': + '@angular/compiler@22.1.6': + dependencies: + tslib: 2.8.1 + + '@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)': dependencies: rxjs: 7.8.2 tslib: 2.8.1 optionalDependencies: - '@angular/compiler': 20.3.18 - zone.js: 0.15.0 + '@angular/compiler': 22.1.6 + zone.js: 0.16.1 - '@angular/forms@20.3.18(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2)': + '@angular/forms@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2)': dependencies: - '@angular/common': 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) - '@angular/core': 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/platform-browser': 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) + '@angular/common': 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/core': 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@standard-schema/spec': 1.1.0 rxjs: 7.8.2 tslib: 2.8.1 + zod: 4.4.3 - '@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))': + '@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))': dependencies: - '@angular/common': 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) - '@angular/core': 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/common': 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/core': 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) tslib: 2.8.1 - optionalDependencies: - '@angular/animations': 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - '@angular/router@20.3.18(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2)': + '@angular/platform-server@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/compiler@22.1.6)(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2)': + dependencies: + '@angular/common': 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/compiler': 22.1.6 + '@angular/core': 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + rxjs: 7.8.2 + tslib: 2.8.1 + xhr2: 0.2.1 + + '@angular/router@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2)': dependencies: - '@angular/common': 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) - '@angular/core': 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/platform-browser': 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) + '@angular/common': 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/core': 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) rxjs: 7.8.2 tslib: 2.8.1 + '@angular/ssr@22.1.8(caf12b5b30d21bb6295944d46eee472d)': + dependencies: + '@angular/common': 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/core': 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/router': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + tslib: 2.8.1 + optionalDependencies: + '@angular/platform-server': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/compiler@22.1.6)(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) + '@arethetypeswrong/cli@0.15.4': dependencies: '@arethetypeswrong/core': 0.15.1 @@ -17431,10 +18099,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/node@9.5.5(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0))': + '@astrojs/node@9.5.5(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0))': dependencies: '@astrojs/internal-helpers': 0.7.6 - astro: 5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0) + astro: 5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0) send: 1.2.1 server-destroy: 1.0.1 transitivePeerDependencies: @@ -17444,11 +18112,11 @@ snapshots: dependencies: prismjs: 1.30.0 - '@astrojs/solid-js@5.1.3(@testing-library/jest-dom@6.9.1)(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(solid-js@1.9.12)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)': + '@astrojs/solid-js@5.1.3(@testing-library/jest-dom@6.9.1)(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(solid-js@1.9.12)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)': dependencies: solid-js: 1.9.12 - vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vite-plugin-solid: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite-plugin-solid: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) transitivePeerDependencies: - '@testing-library/jest-dom' - '@types/node' @@ -17464,9 +18132,9 @@ snapshots: - tsx - yaml - '@astrojs/tailwind@6.0.2(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0))(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.9.0))': + '@astrojs/tailwind@6.0.2(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0))(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.9.0))': dependencies: - astro: 5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0) + astro: 5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0) autoprefixer: 10.4.27(postcss@8.5.8) postcss: 8.5.8 postcss-load-config: 4.0.2(postcss@8.5.8) @@ -17486,14 +18154,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/vercel@8.2.11(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0))(next@16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0))(react@19.2.4)(rollup@4.60.1)(svelte@5.55.1)(vue@3.5.31(typescript@5.8.3))': + '@astrojs/vercel@8.2.11(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0))(next@16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0))(react@19.2.4)(rollup@4.60.1)(svelte@5.55.1)(vue@3.5.31(typescript@5.8.3))': dependencies: '@astrojs/internal-helpers': 0.7.4 - '@vercel/analytics': 1.6.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(next@16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0))(react@19.2.4)(svelte@5.55.1)(vue@3.5.31(typescript@5.8.3)) + '@vercel/analytics': 1.6.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(next@16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0))(react@19.2.4)(svelte@5.55.1)(vue@3.5.31(typescript@5.8.3)) '@vercel/functions': 2.2.13 '@vercel/nft': 0.30.3(rollup@4.60.1) '@vercel/routing-utils': 5.3.3 - astro: 5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0) + astro: 5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0) esbuild: 0.27.4 tinyglobby: 0.2.17 transitivePeerDependencies: @@ -17529,27 +18197,14 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@8.0.0': + dependencies: + '@babel/helper-validator-identifier': 8.0.4 + js-tokens: 10.0.0 + '@babel/compat-data@7.29.7': {} - '@babel/core@7.28.3': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.8 - '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.28.3) - '@babel/helpers': 7.29.7 - '@babel/parser': 7.29.8 - '@babel/template': 7.29.7 - '@babel/traverse': 7.29.8 - '@babel/types': 7.29.8 - convert-source-map: 2.0.0 - debug: 4.4.3 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color + '@babel/compat-data@8.0.0': {} '@babel/core@7.29.7': dependencies: @@ -17571,6 +18226,25 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/core@8.0.1': + dependencies: + '@babel/code-frame': 8.0.0 + '@babel/generator': 8.0.0 + '@babel/helper-compilation-targets': 8.0.0 + '@babel/helpers': 8.0.0 + '@babel/parser': 8.0.4 + '@babel/template': 8.0.0 + '@babel/traverse': 8.0.4 + '@babel/types': 8.0.4 + '@types/gensync': 1.0.5 + convert-source-map: 2.0.0 + empathic: 2.0.1 + gensync: 1.0.0-beta.2 + import-meta-resolve: 4.2.0 + json5: 2.2.3 + obug: 2.1.4 + semver: 7.8.5 + '@babel/eslint-parser@7.28.6(@babel/core@7.29.7)(eslint@9.39.4(jiti@2.7.0))': dependencies: '@babel/core': 7.29.7 @@ -17587,10 +18261,23 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 + '@babel/generator@8.0.0': + dependencies: + '@babel/parser': 8.0.4 + '@babel/types': 8.0.4 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@types/jsesc': 2.5.1 + jsesc: 3.1.0 + '@babel/helper-annotate-as-pure@7.27.3': dependencies: '@babel/types': 7.29.8 + '@babel/helper-annotate-as-pure@8.0.0': + dependencies: + '@babel/types': 8.0.4 + '@babel/helper-compilation-targets@7.29.7': dependencies: '@babel/compat-data': 7.29.7 @@ -17599,6 +18286,14 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-compilation-targets@8.0.0': + dependencies: + '@babel/compat-data': 8.0.0 + '@babel/helper-validator-option': 8.0.0 + browserslist: 4.28.2 + lru-cache: 11.2.7 + semver: 7.8.5 + '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17612,6 +18307,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.28.6(@babel/core@8.0.1) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.29.8 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17619,6 +18328,14 @@ snapshots: regexpu-core: 6.4.0 semver: 6.3.1 + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-annotate-as-pure': 7.27.3 + regexpu-core: 6.4.0 + semver: 6.3.1 + optional: true + '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17630,8 +18347,22 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.28.6 + debug: 4.4.3 + lodash.debounce: 4.0.8 + resolve: 1.22.11 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/helper-globals@7.29.7': {} + '@babel/helper-globals@8.0.0': {} + '@babel/helper-member-expression-to-functions@7.28.5': dependencies: '@babel/traverse': 7.29.8 @@ -17650,23 +18381,24 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.28.3)': + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': dependencies: - '@babel/core': 7.28.3 + '@babel/core': 7.29.7 '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 '@babel/traverse': 7.29.8 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + '@babel/helper-module-transforms@7.29.7(@babel/core@8.0.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 8.0.1 '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 '@babel/traverse': 7.29.8 transitivePeerDependencies: - supports-color + optional: true '@babel/helper-optimise-call-expression@7.27.1': dependencies: @@ -17683,6 +18415,16 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-wrap-function': 7.28.6 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17692,6 +18434,16 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-replace-supers@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: '@babel/traverse': 7.29.8 @@ -17705,10 +18457,16 @@ snapshots: '@babel/helper-string-parser@7.29.7': {} + '@babel/helper-string-parser@8.0.0': {} + '@babel/helper-validator-identifier@7.29.7': {} + '@babel/helper-validator-identifier@8.0.4': {} + '@babel/helper-validator-option@7.29.7': {} + '@babel/helper-validator-option@8.0.0': {} + '@babel/helper-wrap-function@7.28.6': dependencies: '@babel/template': 7.29.7 @@ -17722,6 +18480,11 @@ snapshots: '@babel/template': 7.29.7 '@babel/types': 7.29.8 + '@babel/helpers@8.0.0': + dependencies: + '@babel/template': 8.0.0 + '@babel/types': 8.0.4 + '@babel/highlight@7.25.9': dependencies: '@babel/helper-validator-identifier': 7.29.7 @@ -17733,6 +18496,10 @@ snapshots: dependencies: '@babel/types': 7.29.8 + '@babel/parser@8.0.4': + dependencies: + '@babel/types': 8.0.4 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17741,16 +18508,37 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17760,6 +18548,16 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@8.0.1) + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17768,6 +18566,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17809,6 +18616,11 @@ snapshots: dependencies: '@babel/core': 7.29.7 + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + optional: true + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17854,11 +18666,23 @@ snapshots: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17874,6 +18698,11 @@ snapshots: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17925,11 +18754,24 @@ snapshots: '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.7) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17939,6 +18781,16 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@8.0.1) + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17948,16 +18800,38 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@8.0.1) + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17966,6 +18840,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-class-properties@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17974,6 +18857,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -17986,12 +18878,32 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-classes@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@8.0.1) + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 '@babel/template': 7.29.7 + '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/template': 7.29.7 + optional: true + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18000,28 +18912,63 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.7) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.7) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18030,16 +18977,37 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@8.0.1) + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-flow-strip-types@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18054,6 +19022,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-for-of@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18063,26 +19040,60 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-function-name@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-json-strings@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-literals@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18091,6 +19102,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-module-transforms': 7.29.7(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18099,6 +19119,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-module-transforms': 7.29.7(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18109,6 +19138,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-module-transforms': 7.29.7(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18117,27 +19157,61 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-module-transforms': 7.29.7(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.7) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-new-target@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18149,6 +19223,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@8.0.1) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@8.0.1) + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18157,11 +19243,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-object-super@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@8.0.1) + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18170,11 +19271,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-parameters@7.27.7(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18183,6 +19299,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-private-methods@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18192,11 +19317,27 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18209,6 +19350,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@8.0.1) + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18230,6 +19378,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@8.0.1) + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18241,17 +19400,36 @@ snapshots: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-regenerator@7.29.0(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.7) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-runtime@7.29.0(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18269,6 +19447,12 @@ snapshots: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18277,21 +19461,48 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-spread@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18308,24 +19519,51 @@ snapshots: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.7) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.7) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.7) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/preset-env@7.29.2(@babel/core@7.29.7)': dependencies: '@babel/compat-data': 7.29.7 @@ -18402,6 +19640,83 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/preset-env@7.29.2(@babel/core@8.0.1)': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/core': 8.0.1 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.29.7 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@8.0.1) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@8.0.1) + '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@8.0.1) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@8.0.1) + '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-classes': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@8.0.1) + '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.0(@babel/core@8.0.1) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-explicit-resource-management': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-modules-systemjs': 7.29.0(@babel/core@8.0.1) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@8.0.1) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@8.0.1) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@8.0.1) + '@babel/plugin-transform-regexp-modifiers': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-spread': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-unicode-property-regex': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@8.0.1) + '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@8.0.1) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@8.0.1) + babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@8.0.1) + babel-plugin-polyfill-corejs3: 0.14.2(@babel/core@8.0.1) + babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@8.0.1) + core-js-compat: 3.49.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + optional: true + '@babel/preset-flow@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18416,6 +19731,14 @@ snapshots: '@babel/types': 7.29.8 esutils: 2.0.3 + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/types': 7.29.8 + esutils: 2.0.3 + optional: true + '@babel/preset-react@7.28.5(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -18458,6 +19781,12 @@ snapshots: '@babel/parser': 7.29.8 '@babel/types': 7.29.8 + '@babel/template@8.0.0': + dependencies: + '@babel/code-frame': 8.0.0 + '@babel/parser': 8.0.4 + '@babel/types': 8.0.4 + '@babel/traverse@7.29.8': dependencies: '@babel/code-frame': 7.29.7 @@ -18470,11 +19799,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@8.0.4': + dependencies: + '@babel/code-frame': 8.0.0 + '@babel/generator': 8.0.0 + '@babel/helper-globals': 8.0.0 + '@babel/parser': 8.0.4 + '@babel/template': 8.0.0 + '@babel/types': 8.0.4 + obug: 2.1.4 + '@babel/types@7.29.8': dependencies: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 + '@babel/types@8.0.4': + dependencies: + '@babel/helper-string-parser': 8.0.0 + '@babel/helper-validator-identifier': 8.0.4 + '@callstack/react-theme-provider@3.0.9(react@19.2.4)': dependencies: deepmerge: 3.3.0 @@ -18538,7 +19882,7 @@ snapshots: '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@changesets/write': 0.4.0 - '@inquirer/external-editor': 1.0.3(@types/node@22.19.15) + '@inquirer/external-editor': 3.0.5(@types/node@22.19.15) '@manypkg/get-packages': 1.1.3 ansi-colors: 4.1.3 enquirer: 2.4.1 @@ -19521,8 +20865,6 @@ snapshots: '@floating-ui/utils@0.2.11': {} - '@gar/promise-retry@1.0.3': {} - '@gerrit0/mini-shiki@3.23.0': dependencies: '@shikijs/engine-oniguruma': 3.23.0 @@ -19535,6 +20877,9 @@ snapshots: dependencies: graphql: 16.13.2 + '@harperfast/extended-iterable@1.0.3': + optional: true + '@hono/node-server@1.19.12(hono@4.12.9)': dependencies: hono: 4.12.9 @@ -19649,27 +20994,28 @@ snapshots: '@inquirer/ansi@1.0.2': {} - '@inquirer/checkbox@4.3.2(@types/node@22.19.15)': + '@inquirer/ansi@2.0.8': {} + + '@inquirer/checkbox@5.2.5(@types/node@22.19.15)': dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.15) - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.15) - yoctocolors-cjs: 2.1.3 + '@inquirer/ansi': 2.0.8 + '@inquirer/core': 12.0.3(@types/node@22.19.15) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@22.19.15) optionalDependencies: '@types/node': 22.19.15 - '@inquirer/confirm@5.1.14(@types/node@22.19.15)': + '@inquirer/confirm@5.1.21(@types/node@22.19.15)': dependencies: '@inquirer/core': 10.3.2(@types/node@22.19.15) '@inquirer/type': 3.0.10(@types/node@22.19.15) optionalDependencies: '@types/node': 22.19.15 - '@inquirer/confirm@5.1.21(@types/node@22.19.15)': + '@inquirer/confirm@6.1.1(@types/node@22.19.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.15) - '@inquirer/type': 3.0.10(@types/node@22.19.15) + '@inquirer/core': 11.2.1(@types/node@22.19.15) + '@inquirer/type': 4.1.1(@types/node@22.19.15) optionalDependencies: '@types/node': 22.19.15 @@ -19686,23 +21032,46 @@ snapshots: optionalDependencies: '@types/node': 22.19.15 - '@inquirer/editor@4.2.23(@types/node@22.19.15)': + '@inquirer/core@11.2.1(@types/node@22.19.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.15) - '@inquirer/external-editor': 1.0.3(@types/node@22.19.15) - '@inquirer/type': 3.0.10(@types/node@22.19.15) + '@inquirer/ansi': 2.0.8 + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@22.19.15) + cli-width: 4.1.0 + fast-wrap-ansi: 0.2.2 + mute-stream: 3.0.0 + signal-exit: 4.1.0 optionalDependencies: '@types/node': 22.19.15 - '@inquirer/expand@4.0.23(@types/node@22.19.15)': + '@inquirer/core@12.0.3(@types/node@22.19.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.15) - '@inquirer/type': 3.0.10(@types/node@22.19.15) - yoctocolors-cjs: 2.1.3 + '@inquirer/ansi': 2.0.8 + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@22.19.15) + cli-width: 4.1.0 + fast-wrap-ansi: 0.2.2 + mute-stream: 3.0.0 + signal-exit: 4.1.0 + optionalDependencies: + '@types/node': 22.19.15 + + '@inquirer/editor@5.3.3(@types/node@22.19.15)': + dependencies: + '@inquirer/core': 12.0.3(@types/node@22.19.15) + '@inquirer/external-editor': 3.0.5(@types/node@22.19.15) + '@inquirer/type': 4.1.1(@types/node@22.19.15) + optionalDependencies: + '@types/node': 22.19.15 + + '@inquirer/expand@5.1.5(@types/node@22.19.15)': + dependencies: + '@inquirer/core': 12.0.3(@types/node@22.19.15) + '@inquirer/type': 4.1.1(@types/node@22.19.15) optionalDependencies: '@types/node': 22.19.15 - '@inquirer/external-editor@1.0.3(@types/node@22.19.15)': + '@inquirer/external-editor@3.0.5(@types/node@22.19.15)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 @@ -19711,67 +21080,66 @@ snapshots: '@inquirer/figures@1.0.15': {} - '@inquirer/input@4.3.1(@types/node@22.19.15)': + '@inquirer/figures@2.0.9': {} + + '@inquirer/input@5.1.6(@types/node@22.19.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.15) - '@inquirer/type': 3.0.10(@types/node@22.19.15) + '@inquirer/core': 12.0.3(@types/node@22.19.15) + '@inquirer/type': 4.1.1(@types/node@22.19.15) optionalDependencies: '@types/node': 22.19.15 - '@inquirer/number@3.0.23(@types/node@22.19.15)': + '@inquirer/number@4.2.3(@types/node@22.19.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.15) - '@inquirer/type': 3.0.10(@types/node@22.19.15) + '@inquirer/core': 12.0.3(@types/node@22.19.15) + '@inquirer/type': 4.1.1(@types/node@22.19.15) optionalDependencies: '@types/node': 22.19.15 - '@inquirer/password@4.0.23(@types/node@22.19.15)': + '@inquirer/password@5.2.2(@types/node@22.19.15)': dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.15) - '@inquirer/type': 3.0.10(@types/node@22.19.15) + '@inquirer/ansi': 2.0.8 + '@inquirer/core': 12.0.3(@types/node@22.19.15) + '@inquirer/type': 4.1.1(@types/node@22.19.15) optionalDependencies: '@types/node': 22.19.15 - '@inquirer/prompts@7.8.2(@types/node@22.19.15)': - dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@22.19.15) - '@inquirer/confirm': 5.1.21(@types/node@22.19.15) - '@inquirer/editor': 4.2.23(@types/node@22.19.15) - '@inquirer/expand': 4.0.23(@types/node@22.19.15) - '@inquirer/input': 4.3.1(@types/node@22.19.15) - '@inquirer/number': 3.0.23(@types/node@22.19.15) - '@inquirer/password': 4.0.23(@types/node@22.19.15) - '@inquirer/rawlist': 4.1.11(@types/node@22.19.15) - '@inquirer/search': 3.2.2(@types/node@22.19.15) - '@inquirer/select': 4.4.2(@types/node@22.19.15) + '@inquirer/prompts@8.5.2(@types/node@22.19.15)': + dependencies: + '@inquirer/checkbox': 5.2.5(@types/node@22.19.15) + '@inquirer/confirm': 6.1.1(@types/node@22.19.15) + '@inquirer/editor': 5.3.3(@types/node@22.19.15) + '@inquirer/expand': 5.1.5(@types/node@22.19.15) + '@inquirer/input': 5.1.6(@types/node@22.19.15) + '@inquirer/number': 4.2.3(@types/node@22.19.15) + '@inquirer/password': 5.2.2(@types/node@22.19.15) + '@inquirer/rawlist': 5.3.5(@types/node@22.19.15) + '@inquirer/search': 4.3.3(@types/node@22.19.15) + '@inquirer/select': 5.2.5(@types/node@22.19.15) optionalDependencies: '@types/node': 22.19.15 - '@inquirer/rawlist@4.1.11(@types/node@22.19.15)': + '@inquirer/rawlist@5.3.5(@types/node@22.19.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.15) - '@inquirer/type': 3.0.10(@types/node@22.19.15) - yoctocolors-cjs: 2.1.3 + '@inquirer/core': 12.0.3(@types/node@22.19.15) + '@inquirer/type': 4.1.1(@types/node@22.19.15) optionalDependencies: '@types/node': 22.19.15 - '@inquirer/search@3.2.2(@types/node@22.19.15)': + '@inquirer/search@4.3.3(@types/node@22.19.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.15) - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.15) - yoctocolors-cjs: 2.1.3 + '@inquirer/core': 12.0.3(@types/node@22.19.15) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@22.19.15) optionalDependencies: '@types/node': 22.19.15 - '@inquirer/select@4.4.2(@types/node@22.19.15)': + '@inquirer/select@5.2.5(@types/node@22.19.15)': dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.15) - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.15) - yoctocolors-cjs: 2.1.3 + '@inquirer/ansi': 2.0.8 + '@inquirer/core': 12.0.3(@types/node@22.19.15) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@22.19.15) optionalDependencies: '@types/node': 22.19.15 @@ -19779,6 +21147,10 @@ snapshots: optionalDependencies: '@types/node': 22.19.15 + '@inquirer/type@4.1.1(@types/node@22.19.15)': + optionalDependencies: + '@types/node': 22.19.15 + '@internationalized/date@3.12.0': dependencies: '@swc/helpers': 0.5.20 @@ -20004,11 +21376,11 @@ snapshots: '@solid-primitives/utils': 6.4.0(solid-js@1.9.12) solid-js: 1.9.12 - '@listr2/prompt-adapter-inquirer@3.0.1(@inquirer/prompts@7.8.2(@types/node@22.19.15))(@types/node@22.19.15)(listr2@9.0.1)': + '@listr2/prompt-adapter-inquirer@4.2.5(@inquirer/prompts@8.5.2(@types/node@22.19.15))(@types/node@22.19.15)(listr2@11.0.0)': dependencies: - '@inquirer/prompts': 7.8.2(@types/node@22.19.15) - '@inquirer/type': 3.0.10(@types/node@22.19.15) - listr2: 9.0.1 + '@inquirer/prompts': 8.5.2(@types/node@22.19.15) + '@inquirer/type': 4.1.1(@types/node@22.19.15) + listr2: 11.0.0 transitivePeerDependencies: - '@types/node' @@ -20042,25 +21414,25 @@ snapshots: dependencies: '@lit-labs/ssr-dom-shim': 1.5.1 - '@lmdb/lmdb-darwin-arm64@3.4.2': + '@lmdb/lmdb-darwin-arm64@3.5.6': optional: true - '@lmdb/lmdb-darwin-x64@3.4.2': + '@lmdb/lmdb-darwin-x64@3.5.6': optional: true - '@lmdb/lmdb-linux-arm64@3.4.2': + '@lmdb/lmdb-linux-arm64@3.5.6': optional: true - '@lmdb/lmdb-linux-arm@3.4.2': + '@lmdb/lmdb-linux-arm@3.5.6': optional: true - '@lmdb/lmdb-linux-x64@3.4.2': + '@lmdb/lmdb-linux-x64@3.5.6': optional: true - '@lmdb/lmdb-win32-arm64@3.4.2': + '@lmdb/lmdb-win32-arm64@3.5.6': optional: true - '@lmdb/lmdb-win32-x64@3.4.2': + '@lmdb/lmdb-win32-x64@3.5.6': optional: true '@manypkg/find-root@1.1.0': @@ -20131,7 +21503,7 @@ snapshots: '@microsoft/tsdoc@0.15.1': {} - '@modelcontextprotocol/sdk@1.26.0(zod@4.1.13)': + '@modelcontextprotocol/sdk@1.30.0(zod@4.4.3)': dependencies: '@hono/node-server': 1.19.12(hono@4.12.9) ajv: 8.18.0 @@ -20148,8 +21520,8 @@ snapshots: json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 raw-body: 3.0.2 - zod: 4.1.13 - zod-to-json-schema: 3.25.2(zod@4.1.13) + zod: 4.4.3 + zod-to-json-schema: 3.25.2(zod@4.4.3) transitivePeerDependencies: - supports-color @@ -20369,68 +21741,10 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@npmcli/agent@4.0.0': - dependencies: - agent-base: 7.1.4 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - lru-cache: 11.2.7 - socks-proxy-agent: 8.0.5 - transitivePeerDependencies: - - supports-color - '@npmcli/fs@3.1.1': dependencies: semver: 7.7.4 - '@npmcli/fs@5.0.0': - dependencies: - semver: 7.7.4 - - '@npmcli/git@7.0.2': - dependencies: - '@gar/promise-retry': 1.0.3 - '@npmcli/promise-spawn': 9.0.1 - ini: 6.0.0 - lru-cache: 11.2.7 - npm-pick-manifest: 11.0.3 - proc-log: 6.1.0 - semver: 7.7.4 - which: 6.0.1 - - '@npmcli/installed-package-contents@4.0.0': - dependencies: - npm-bundled: 5.0.0 - npm-normalize-package-bin: 5.0.0 - - '@npmcli/node-gyp@5.0.0': {} - - '@npmcli/package-json@7.0.5': - dependencies: - '@npmcli/git': 7.0.2 - glob: 13.0.6 - hosted-git-info: 9.0.2 - json-parse-even-better-errors: 5.0.0 - proc-log: 6.1.0 - semver: 7.7.4 - spdx-expression-parse: 4.0.0 - - '@npmcli/promise-spawn@9.0.1': - dependencies: - which: 6.0.1 - - '@npmcli/redact@4.0.0': {} - - '@npmcli/run-script@10.0.4': - dependencies: - '@npmcli/node-gyp': 5.0.0 - '@npmcli/package-json': 7.0.5 - '@npmcli/promise-spawn': 9.0.1 - node-gyp: 12.2.0 - proc-log: 6.1.0 - transitivePeerDependencies: - - supports-color - '@nx/nx-darwin-arm64@22.1.3': optional: true @@ -20472,63 +21786,198 @@ snapshots: '@oslojs/encoding@1.1.0': {} + '@oxc-parser/binding-android-arm-eabi@0.121.0': + optional: true + + '@oxc-parser/binding-android-arm-eabi@0.142.0': + optional: true + '@oxc-parser/binding-android-arm-eabi@0.143.0': optional: true + '@oxc-parser/binding-android-arm64@0.121.0': + optional: true + + '@oxc-parser/binding-android-arm64@0.142.0': + optional: true + '@oxc-parser/binding-android-arm64@0.143.0': optional: true + '@oxc-parser/binding-darwin-arm64@0.121.0': + optional: true + + '@oxc-parser/binding-darwin-arm64@0.142.0': + optional: true + '@oxc-parser/binding-darwin-arm64@0.143.0': optional: true + '@oxc-parser/binding-darwin-x64@0.121.0': + optional: true + + '@oxc-parser/binding-darwin-x64@0.142.0': + optional: true + '@oxc-parser/binding-darwin-x64@0.143.0': optional: true + '@oxc-parser/binding-freebsd-x64@0.121.0': + optional: true + + '@oxc-parser/binding-freebsd-x64@0.142.0': + optional: true + '@oxc-parser/binding-freebsd-x64@0.143.0': optional: true + '@oxc-parser/binding-linux-arm-gnueabihf@0.121.0': + optional: true + + '@oxc-parser/binding-linux-arm-gnueabihf@0.142.0': + optional: true + '@oxc-parser/binding-linux-arm-gnueabihf@0.143.0': optional: true + '@oxc-parser/binding-linux-arm-musleabihf@0.121.0': + optional: true + + '@oxc-parser/binding-linux-arm-musleabihf@0.142.0': + optional: true + '@oxc-parser/binding-linux-arm-musleabihf@0.143.0': optional: true + '@oxc-parser/binding-linux-arm64-gnu@0.121.0': + optional: true + + '@oxc-parser/binding-linux-arm64-gnu@0.142.0': + optional: true + '@oxc-parser/binding-linux-arm64-gnu@0.143.0': optional: true + '@oxc-parser/binding-linux-arm64-musl@0.121.0': + optional: true + + '@oxc-parser/binding-linux-arm64-musl@0.142.0': + optional: true + '@oxc-parser/binding-linux-arm64-musl@0.143.0': optional: true + '@oxc-parser/binding-linux-ppc64-gnu@0.121.0': + optional: true + + '@oxc-parser/binding-linux-ppc64-gnu@0.142.0': + optional: true + '@oxc-parser/binding-linux-ppc64-gnu@0.143.0': optional: true + '@oxc-parser/binding-linux-riscv64-gnu@0.121.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-gnu@0.142.0': + optional: true + '@oxc-parser/binding-linux-riscv64-gnu@0.143.0': optional: true + '@oxc-parser/binding-linux-riscv64-musl@0.121.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-musl@0.142.0': + optional: true + '@oxc-parser/binding-linux-riscv64-musl@0.143.0': optional: true + '@oxc-parser/binding-linux-s390x-gnu@0.121.0': + optional: true + + '@oxc-parser/binding-linux-s390x-gnu@0.142.0': + optional: true + '@oxc-parser/binding-linux-s390x-gnu@0.143.0': optional: true + '@oxc-parser/binding-linux-x64-gnu@0.121.0': + optional: true + + '@oxc-parser/binding-linux-x64-gnu@0.142.0': + optional: true + '@oxc-parser/binding-linux-x64-gnu@0.143.0': optional: true + '@oxc-parser/binding-linux-x64-musl@0.121.0': + optional: true + + '@oxc-parser/binding-linux-x64-musl@0.142.0': + optional: true + '@oxc-parser/binding-linux-x64-musl@0.143.0': optional: true + '@oxc-parser/binding-openharmony-arm64@0.121.0': + optional: true + + '@oxc-parser/binding-openharmony-arm64@0.142.0': + optional: true + '@oxc-parser/binding-openharmony-arm64@0.143.0': optional: true + '@oxc-parser/binding-wasm32-wasi@0.121.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + optional: true + + '@oxc-parser/binding-wasm32-wasi@0.142.0': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.121.0': + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.142.0': + optional: true + '@oxc-parser/binding-win32-arm64-msvc@0.143.0': optional: true + '@oxc-parser/binding-win32-ia32-msvc@0.121.0': + optional: true + + '@oxc-parser/binding-win32-ia32-msvc@0.142.0': + optional: true + '@oxc-parser/binding-win32-ia32-msvc@0.143.0': optional: true + '@oxc-parser/binding-win32-x64-msvc@0.121.0': + optional: true + + '@oxc-parser/binding-win32-x64-msvc@0.142.0': + optional: true + '@oxc-parser/binding-win32-x64-msvc@0.143.0': optional: true + '@oxc-project/types@0.121.0': {} + + '@oxc-project/types@0.140.0': {} + + '@oxc-project/types@0.142.0': {} + '@oxc-project/types@0.143.0': {} '@oxc-project/types@0.144.0': {} @@ -20689,19 +22138,38 @@ snapshots: '@poppinss/exception@1.2.3': {} - '@preact/preset-vite@2.10.5(@babel/core@7.29.7)(preact@10.29.0)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@preact/preset-vite@2.10.5(@babel/core@7.29.7)(preact@10.29.0)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.7 '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.7) '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.29.7) - '@prefresh/vite': 2.4.12(preact@10.29.0)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@prefresh/vite': 2.4.12(preact@10.29.0)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@rollup/pluginutils': 5.3.0(rollup@4.60.1) babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.29.7) debug: 4.4.3 magic-string: 0.30.21 picocolors: 1.1.1 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vite-prerender-plugin: 0.5.13(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite-prerender-plugin: 0.5.13(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + zimmerframe: 1.1.4 + transitivePeerDependencies: + - preact + - rollup + - supports-color + + '@preact/preset-vite@2.10.5(@babel/core@8.0.1)(preact@10.29.0)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + dependencies: + '@babel/core': 8.0.1 + '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@8.0.1) + '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@8.0.1) + '@prefresh/vite': 2.4.12(preact@10.29.0)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@rollup/pluginutils': 5.3.0(rollup@4.60.1) + babel-plugin-transform-hook-names: 1.0.2(@babel/core@8.0.1) + debug: 4.4.3 + magic-string: 0.30.21 + picocolors: 1.1.1 + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite-prerender-plugin: 0.5.13(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) zimmerframe: 1.1.4 transitivePeerDependencies: - preact @@ -20716,7 +22184,7 @@ snapshots: '@prefresh/utils@1.2.1': {} - '@prefresh/vite@2.4.12(preact@10.29.0)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@prefresh/vite@2.4.12(preact@10.29.0)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.7 '@prefresh/babel-plugin': 0.5.3 @@ -20724,7 +22192,7 @@ snapshots: '@prefresh/utils': 1.2.1 '@rollup/pluginutils': 4.2.1 preact: 10.29.0 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) transitivePeerDependencies: - supports-color @@ -20926,45 +22394,94 @@ snapshots: '@remix-run/router@1.23.2': {} + '@rolldown/binding-android-arm64@1.2.0': + optional: true + '@rolldown/binding-android-arm64@1.2.4': optional: true + '@rolldown/binding-darwin-arm64@1.2.0': + optional: true + '@rolldown/binding-darwin-arm64@1.2.4': optional: true + '@rolldown/binding-darwin-x64@1.2.0': + optional: true + '@rolldown/binding-darwin-x64@1.2.4': optional: true + '@rolldown/binding-freebsd-x64@1.2.0': + optional: true + '@rolldown/binding-freebsd-x64@1.2.4': optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.2.0': + optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.2.4': optional: true + '@rolldown/binding-linux-arm64-gnu@1.2.0': + optional: true + '@rolldown/binding-linux-arm64-gnu@1.2.4': optional: true + '@rolldown/binding-linux-arm64-musl@1.2.0': + optional: true + '@rolldown/binding-linux-arm64-musl@1.2.4': optional: true + '@rolldown/binding-linux-ppc64-gnu@1.2.0': + optional: true + '@rolldown/binding-linux-ppc64-gnu@1.2.4': optional: true + '@rolldown/binding-linux-s390x-gnu@1.2.0': + optional: true + '@rolldown/binding-linux-s390x-gnu@1.2.4': optional: true + '@rolldown/binding-linux-x64-gnu@1.2.0': + optional: true + '@rolldown/binding-linux-x64-gnu@1.2.4': optional: true + '@rolldown/binding-linux-x64-musl@1.2.0': + optional: true + '@rolldown/binding-linux-x64-musl@1.2.4': optional: true + '@rolldown/binding-openharmony-arm64@1.2.0': + optional: true + '@rolldown/binding-openharmony-arm64@1.2.4': optional: true + '@rolldown/binding-wasm32-wasi@1.2.0': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.2.0': + optional: true + '@rolldown/binding-win32-arm64-msvc@1.2.4': optional: true + '@rolldown/binding-win32-x64-msvc@1.2.0': + optional: true + '@rolldown/binding-win32-x64-msvc@1.2.4': optional: true @@ -21040,153 +22557,78 @@ snapshots: optionalDependencies: rollup: 4.60.1 - '@rollup/rollup-android-arm-eabi@4.59.0': - optional: true - '@rollup/rollup-android-arm-eabi@4.60.1': optional: true - '@rollup/rollup-android-arm64@4.59.0': - optional: true - '@rollup/rollup-android-arm64@4.60.1': optional: true - '@rollup/rollup-darwin-arm64@4.59.0': - optional: true - '@rollup/rollup-darwin-arm64@4.60.1': optional: true - '@rollup/rollup-darwin-x64@4.59.0': - optional: true - '@rollup/rollup-darwin-x64@4.60.1': optional: true - '@rollup/rollup-freebsd-arm64@4.59.0': - optional: true - '@rollup/rollup-freebsd-arm64@4.60.1': optional: true - '@rollup/rollup-freebsd-x64@4.59.0': - optional: true - '@rollup/rollup-freebsd-x64@4.60.1': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.60.1': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.59.0': - optional: true - '@rollup/rollup-linux-arm-musleabihf@4.60.1': optional: true - '@rollup/rollup-linux-arm64-gnu@4.59.0': - optional: true - '@rollup/rollup-linux-arm64-gnu@4.60.1': optional: true - '@rollup/rollup-linux-arm64-musl@4.59.0': - optional: true - '@rollup/rollup-linux-arm64-musl@4.60.1': optional: true - '@rollup/rollup-linux-loong64-gnu@4.59.0': - optional: true - '@rollup/rollup-linux-loong64-gnu@4.60.1': optional: true - '@rollup/rollup-linux-loong64-musl@4.59.0': - optional: true - '@rollup/rollup-linux-loong64-musl@4.60.1': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.59.0': - optional: true - '@rollup/rollup-linux-ppc64-gnu@4.60.1': optional: true - '@rollup/rollup-linux-ppc64-musl@4.59.0': - optional: true - '@rollup/rollup-linux-ppc64-musl@4.60.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.59.0': - optional: true - '@rollup/rollup-linux-riscv64-gnu@4.60.1': optional: true - '@rollup/rollup-linux-riscv64-musl@4.59.0': - optional: true - '@rollup/rollup-linux-riscv64-musl@4.60.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.59.0': - optional: true - '@rollup/rollup-linux-s390x-gnu@4.60.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.59.0': - optional: true - '@rollup/rollup-linux-x64-gnu@4.60.1': optional: true - '@rollup/rollup-linux-x64-musl@4.59.0': - optional: true - '@rollup/rollup-linux-x64-musl@4.60.1': optional: true - '@rollup/rollup-openbsd-x64@4.59.0': - optional: true - '@rollup/rollup-openbsd-x64@4.60.1': optional: true - '@rollup/rollup-openharmony-arm64@4.59.0': - optional: true - '@rollup/rollup-openharmony-arm64@4.60.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.59.0': - optional: true - '@rollup/rollup-win32-arm64-msvc@4.60.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.59.0': - optional: true - '@rollup/rollup-win32-ia32-msvc@4.60.1': optional: true - '@rollup/rollup-win32-x64-gnu@4.59.0': - optional: true - '@rollup/rollup-win32-x64-gnu@4.60.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.59.0': - optional: true - '@rollup/rollup-win32-x64-msvc@4.60.1': optional: true @@ -21224,11 +22666,12 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@schematics/angular@20.3.22(chokidar@5.0.0)': + '@schematics/angular@22.1.8(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 20.3.22(chokidar@5.0.0) - '@angular-devkit/schematics': 20.3.22(chokidar@5.0.0) + '@angular-devkit/core': 22.1.8(chokidar@5.0.0) + '@angular-devkit/schematics': 22.1.8(chokidar@5.0.0) jsonc-parser: 3.3.1 + typescript: 6.0.3 transitivePeerDependencies: - chokidar @@ -21303,38 +22746,6 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} - '@sigstore/bundle@4.0.0': - dependencies: - '@sigstore/protobuf-specs': 0.5.0 - - '@sigstore/core@3.2.0': {} - - '@sigstore/protobuf-specs@0.5.0': {} - - '@sigstore/sign@4.1.1': - dependencies: - '@gar/promise-retry': 1.0.3 - '@sigstore/bundle': 4.0.0 - '@sigstore/core': 3.2.0 - '@sigstore/protobuf-specs': 0.5.0 - make-fetch-happen: 15.0.5 - proc-log: 6.1.0 - transitivePeerDependencies: - - supports-color - - '@sigstore/tuf@4.0.2': - dependencies: - '@sigstore/protobuf-specs': 0.5.0 - tuf-js: 4.1.0 - transitivePeerDependencies: - - supports-color - - '@sigstore/verify@3.1.0': - dependencies: - '@sigstore/bundle': 4.0.0 - '@sigstore/core': 3.2.0 - '@sigstore/protobuf-specs': 0.5.0 - '@sinclair/typebox@0.27.10': {} '@sinclair/typebox@0.34.49': {} @@ -21449,11 +22860,11 @@ snapshots: dependencies: solid-js: 1.9.12 - '@solidjs/start@1.3.2(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@solidjs/start@1.3.2(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: - '@tanstack/server-functions-plugin': 1.121.21(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) - '@vinxi/plugin-directives': 0.5.1(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0)) - '@vinxi/server-components': 0.5.1(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0)) + '@tanstack/server-functions-plugin': 1.121.21(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@vinxi/plugin-directives': 0.5.1(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0)) + '@vinxi/server-components': 0.5.1(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0)) cookie-es: 2.0.0 defu: 6.1.7 error-stack-parser: 2.1.4 @@ -21465,8 +22876,8 @@ snapshots: source-map-js: 1.2.1 terracotta: 1.1.0(solid-js@1.9.12) tinyglobby: 0.2.17 - vinxi: 0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0) - vite-plugin-solid: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vinxi: 0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0) + vite-plugin-solid: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) transitivePeerDependencies: - '@testing-library/jest-dom' - solid-js @@ -21498,15 +22909,15 @@ snapshots: dependencies: acorn: 8.16.0 - '@sveltejs/adapter-auto@6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))': + '@sveltejs/adapter-auto@6.1.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))': dependencies: - '@sveltejs/kit': 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/kit': 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) - '@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@standard-schema/spec': 1.1.0 '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) - '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@types/cookie': 0.6.0 acorn: 8.16.0 cookie: 0.6.0 @@ -21518,16 +22929,16 @@ snapshots: set-cookie-parser: 3.1.0 sirv: 3.0.2 svelte: 5.55.1 - vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) optionalDependencies: typescript: 5.8.3 optional: true - '@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@standard-schema/spec': 1.1.0 '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) - '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@types/cookie': 0.6.0 acorn: 8.16.0 cookie: 0.6.0 @@ -21539,7 +22950,7 @@ snapshots: set-cookie-parser: 3.1.0 sirv: 3.0.2 svelte: 5.55.1 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) optionalDependencies: typescript: 5.8.3 @@ -21554,49 +22965,49 @@ snapshots: transitivePeerDependencies: - typescript - '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) debug: 4.4.3 svelte: 5.55.1 - vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) transitivePeerDependencies: - supports-color optional: true - '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) debug: 4.4.3 svelte: 5.55.1 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) debug: 4.4.3 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.21 svelte: 5.55.1 - vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) transitivePeerDependencies: - supports-color optional: true - '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) debug: 4.4.3 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.21 svelte: 5.55.1 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) transitivePeerDependencies: - supports-color @@ -21676,16 +23087,16 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.2.2 '@tailwindcss/oxide-win32-x64-msvc': 4.2.2 - '@tailwindcss/vite@4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tailwindcss/vite@4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@tailwindcss/node': 4.2.2 '@tailwindcss/oxide': 4.2.2 tailwindcss: 4.2.2 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) '@tanstack/devtools-event-client@0.4.4': {} - '@tanstack/directive-functions-plugin@1.121.21(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/directive-functions-plugin@1.121.21(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@babel/code-frame': 7.26.2 '@babel/core': 7.29.7 @@ -21694,7 +23105,7 @@ snapshots: '@tanstack/router-utils': 1.161.6 babel-dead-code-elimination: 1.0.12 tiny-invariant: 1.3.3 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) transitivePeerDependencies: - supports-color @@ -21758,7 +23169,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/server-functions-plugin@1.121.21(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/server-functions-plugin@1.121.21(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@babel/code-frame': 7.26.2 '@babel/core': 7.29.7 @@ -21767,7 +23178,7 @@ snapshots: '@babel/template': 7.29.7 '@babel/traverse': 7.29.8 '@babel/types': 7.29.8 - '@tanstack/directive-functions-plugin': 1.121.21(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/directive-functions-plugin': 1.121.21(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) babel-dead-code-elimination: 1.0.12 tiny-invariant: 1.3.3 transitivePeerDependencies: @@ -21784,25 +23195,25 @@ snapshots: transitivePeerDependencies: - typescript - '@tanstack/vite-config@0.4.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/vite-config@0.4.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: rollup-plugin-preserve-directives: 0.4.0(rollup@4.60.1) - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vite-plugin-dts: 4.2.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) - vite-plugin-externalize-deps: 0.10.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) - vite-tsconfig-paths: 5.1.4(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite-plugin-dts: 4.2.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite-plugin-externalize-deps: 0.10.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite-tsconfig-paths: 5.1.4(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) transitivePeerDependencies: - '@types/node' - rollup - supports-color - typescript - '@testing-library/angular@18.1.1(3436010aec00f8e828978cdcb451dc36)': + '@testing-library/angular@18.1.1(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(@angular/router@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2))(@testing-library/dom@10.4.1)': dependencies: - '@angular/common': 20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) - '@angular/core': 20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/platform-browser': 20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)) - '@angular/router': 20.3.18(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.3.18(@angular/animations@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.3.18(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.3.18(@angular/compiler@20.3.18)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) + '@angular/common': 22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/core': 22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)) + '@angular/router': 22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@22.1.6(@angular/common@22.1.6(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@22.1.6(@angular/compiler@22.1.6)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) '@testing-library/dom': 10.4.1 tslib: 2.8.1 @@ -21874,23 +23285,23 @@ snapshots: dependencies: svelte: 5.55.1 - '@testing-library/svelte@5.3.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))': + '@testing-library/svelte@5.3.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))': dependencies: '@testing-library/dom': 10.4.1 '@testing-library/svelte-core': 1.0.0(svelte@5.55.1) svelte: 5.55.1 optionalDependencies: - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vitest: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) - - '@tsconfig/svelte@5.0.8': {} + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vitest: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) - '@tufjs/canonical-json@2.0.0': {} - - '@tufjs/models@4.1.0': + '@ts-morph/common@0.22.0': dependencies: - '@tufjs/canonical-json': 2.0.0 - minimatch: 10.2.5 + fast-glob: 3.3.3 + minimatch: 9.0.9 + mkdirp: 3.0.1 + path-browserify: 1.0.1 + + '@tsconfig/svelte@5.0.8': {} '@tybys/wasm-util@0.10.3': dependencies: @@ -21926,6 +23337,11 @@ snapshots: dependencies: '@babel/types': 7.29.8 + '@types/body-parser@1.19.6': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 22.19.15 + '@types/braces@3.0.5': {} '@types/chai@5.2.3': @@ -21933,6 +23349,10 @@ snapshots: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 + '@types/connect@3.4.38': + dependencies: + '@types/node': 22.19.15 + '@types/cookie@0.6.0': {} '@types/debug@4.1.13': @@ -21955,6 +23375,21 @@ snapshots: '@types/estree@1.0.8': {} + '@types/express-serve-static-core@5.1.1': + dependencies: + '@types/node': 22.19.15 + '@types/qs': 6.15.1 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 + + '@types/express@5.0.6': + dependencies: + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 5.1.1 + '@types/serve-static': 2.2.0 + + '@types/gensync@1.0.5': {} + '@types/graceful-fs@4.1.9': dependencies: '@types/node': 22.19.15 @@ -21969,6 +23404,8 @@ snapshots: '@types/html-minifier-terser@6.1.0': {} + '@types/http-errors@2.0.5': {} + '@types/istanbul-lib-coverage@2.0.6': {} '@types/istanbul-lib-report@3.0.3': @@ -21984,6 +23421,8 @@ snapshots: ast-types: 0.16.1 recast: 0.23.11 + '@types/jsesc@2.5.1': {} + '@types/json-schema@7.0.15': {} '@types/mdast@4.0.4': @@ -22010,6 +23449,10 @@ snapshots: '@types/normalize-package-data@2.4.4': {} + '@types/qs@6.15.1': {} + + '@types/range-parser@1.2.7': {} + '@types/react-dom@19.2.3(@types/react@19.2.14)': dependencies: '@types/react': 19.2.14 @@ -22020,6 +23463,15 @@ snapshots: '@types/resolve@1.20.2': {} + '@types/send@1.2.1': + dependencies: + '@types/node': 22.19.15 + + '@types/serve-static@2.2.0': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 22.19.15 + '@types/sort-by@1.2.3': {} '@types/source-list-map@0.1.6': {} @@ -22247,7 +23699,7 @@ snapshots: '@typescript-eslint/visitor-keys': 8.58.1 debug: 4.4.3 minimatch: 10.2.5 - semver: 7.7.4 + semver: 7.8.5 tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@5.8.3) typescript: 5.8.3 @@ -22262,7 +23714,7 @@ snapshots: '@typescript-eslint/visitor-keys': 8.58.1 debug: 4.4.3 minimatch: 10.2.5 - semver: 7.7.4 + semver: 7.8.5 tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 @@ -22277,7 +23729,7 @@ snapshots: '@typescript-eslint/visitor-keys': 8.58.1 debug: 4.4.3 minimatch: 10.2.5 - semver: 7.7.4 + semver: 7.8.5 tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 @@ -22292,7 +23744,7 @@ snapshots: '@typescript-eslint/visitor-keys': 8.58.1 debug: 4.4.3 minimatch: 10.2.5 - semver: 7.7.4 + semver: 7.8.5 tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@7.0.2) typescript: 7.0.2 @@ -22471,10 +23923,10 @@ snapshots: '@urql/core': 5.2.0(graphql@16.13.2) wonka: 6.3.6 - '@vercel/analytics@1.6.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(next@16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0))(react@19.2.4)(svelte@5.55.1)(vue@3.5.31(typescript@5.8.3))': + '@vercel/analytics@1.6.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(next@16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0))(react@19.2.4)(svelte@5.55.1)(vue@3.5.31(typescript@5.8.3))': optionalDependencies: - '@sveltejs/kit': 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) - next: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0) + '@sveltejs/kit': 2.57.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.55.1)(typescript@5.8.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + next: 16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0) react: 19.2.4 svelte: 5.55.1 vue: 3.5.31(typescript@5.8.3) @@ -22553,7 +24005,7 @@ snapshots: untun: 0.1.3 uqr: 0.1.2 - '@vinxi/plugin-directives@0.5.1(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0))': + '@vinxi/plugin-directives@0.5.1(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0))': dependencies: '@babel/parser': 7.29.8 acorn: 8.16.0 @@ -22564,24 +24016,24 @@ snapshots: magicast: 0.2.11 recast: 0.23.11 tslib: 2.8.1 - vinxi: 0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0) + vinxi: 0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0) - '@vinxi/server-components@0.5.1(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0))': + '@vinxi/server-components@0.5.1(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0))': dependencies: - '@vinxi/plugin-directives': 0.5.1(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0)) + '@vinxi/plugin-directives': 0.5.1(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0)) acorn: 8.16.0 acorn-loose: 8.5.2 acorn-typescript: 1.4.13(acorn@8.16.0) astring: 1.9.0 magicast: 0.2.11 recast: 0.23.11 - vinxi: 0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0) + vinxi: 0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0) - '@vitejs/plugin-basic-ssl@2.1.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitejs/plugin-basic-ssl@2.3.0(vite@7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.7 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.7) @@ -22589,21 +24041,21 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3))': + '@vitejs/plugin-vue@5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@5.8.3))': dependencies: - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) vue: 3.5.31(typescript@5.8.3) - '@vitejs/plugin-vue@5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@7.0.2))': + '@vitejs/plugin-vue@5.2.4(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.31(typescript@7.0.2))': dependencies: - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) vue: 3.5.31(typescript@7.0.2) - '@vitest/coverage-istanbul@4.0.6(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))': + '@vitest/coverage-istanbul@4.0.6(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))': dependencies: '@istanbuljs/schema': 0.1.3 debug: 4.4.3 @@ -22614,11 +24066,11 @@ snapshots: istanbul-reports: 3.2.0 magicast: 0.3.5 tinyrainbow: 3.1.0 - vitest: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vitest: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) transitivePeerDependencies: - supports-color - '@vitest/eslint-plugin@1.6.14(@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))': + '@vitest/eslint-plugin@1.6.14(@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)))': dependencies: '@typescript-eslint/scope-manager': 8.58.1 '@typescript-eslint/utils': 8.58.1(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) @@ -22626,7 +24078,7 @@ snapshots: optionalDependencies: '@typescript-eslint/eslint-plugin': 8.58.1(@typescript-eslint/parser@8.58.1(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) typescript: 6.0.3 - vitest: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vitest: 4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) transitivePeerDependencies: - supports-color @@ -22639,33 +24091,42 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.2 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.12.14(@types/node@22.19.15)(typescript@5.9.3) - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - optional: true + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - '@vitest/mocker@4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.2 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.12.14(@types/node@22.19.15)(typescript@6.0.3) - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - '@vitest/mocker@4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@7.0.2))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': + dependencies: + '@vitest/spy': 4.1.2 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + msw: 2.12.14(@types/node@22.19.15)(typescript@6.0.3) + vite: 7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + optional: true + + '@vitest/mocker@4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@7.0.2))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.2 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.12.14(@types/node@22.19.15)(typescript@7.0.2) - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) '@vitest/pretty-format@4.1.2': dependencies: @@ -22802,6 +24263,19 @@ snapshots: '@vue/devtools-api@6.6.4': {} + '@vue/language-core@2.1.6(typescript@5.9.3)': + dependencies: + '@volar/language-core': 2.4.28 + '@vue/compiler-dom': 3.5.31 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.31 + computeds: 0.0.1 + minimatch: 9.0.9 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.9.3 + '@vue/language-core@2.1.6(typescript@6.0.3)': dependencies: '@volar/language-core': 2.4.28 @@ -23149,8 +24623,6 @@ snapshots: abbrev@3.0.1: {} - abbrev@4.0.0: {} - abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -23191,6 +24663,8 @@ snapshots: agent-base@7.1.4: {} + agent-base@9.0.0: {} + aggregate-error@3.1.0: dependencies: clean-stack: 2.2.0 @@ -23213,9 +24687,9 @@ snapshots: dependencies: ajv: 6.14.0 - ajv-formats@2.1.1(ajv@8.18.0): + ajv-formats@2.1.1(ajv@8.20.0): optionalDependencies: - ajv: 8.18.0 + ajv: 8.20.0 ajv-formats@3.0.1(ajv@8.13.0): optionalDependencies: @@ -23225,13 +24699,17 @@ snapshots: optionalDependencies: ajv: 8.18.0 + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + ajv-keywords@3.5.2(ajv@6.14.0): dependencies: ajv: 6.14.0 - ajv-keywords@5.1.0(ajv@8.18.0): + ajv-keywords@5.1.0(ajv@8.20.0): dependencies: - ajv: 8.18.0 + ajv: 8.20.0 fast-deep-equal: 3.1.3 ajv@6.14.0: @@ -23262,22 +24740,12 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - algoliasearch@5.35.0: - dependencies: - '@algolia/abtesting': 1.1.0 - '@algolia/client-abtesting': 5.35.0 - '@algolia/client-analytics': 5.35.0 - '@algolia/client-common': 5.35.0 - '@algolia/client-insights': 5.35.0 - '@algolia/client-personalization': 5.35.0 - '@algolia/client-query-suggestions': 5.35.0 - '@algolia/client-search': 5.35.0 - '@algolia/ingestion': 1.35.0 - '@algolia/monitoring': 1.35.0 - '@algolia/recommend': 5.35.0 - '@algolia/requester-browser-xhr': 5.35.0 - '@algolia/requester-fetch': 5.35.0 - '@algolia/requester-node-http': 5.35.0 + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 alien-signals@1.0.13: {} @@ -23489,7 +24957,7 @@ snapshots: astring@1.9.0: {} - astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0): + astro@5.18.1(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.9.0): dependencies: '@astrojs/compiler': 2.13.1 '@astrojs/internal-helpers': 0.7.6 @@ -23546,8 +25014,8 @@ snapshots: unist-util-visit: 5.1.0 unstorage: 1.17.5(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1) vfile: 6.0.3 - vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 yocto-spinner: 0.2.3 @@ -23717,6 +25185,16 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-polyfill-corejs2@0.4.17(@babel/core@8.0.1): + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/core': 8.0.1 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@8.0.1) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + optional: true + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.29.7): dependencies: '@babel/core': 7.29.7 @@ -23733,6 +25211,15 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-polyfill-corejs3@0.14.2(@babel/core@8.0.1): + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@8.0.1) + core-js-compat: 3.49.0 + transitivePeerDependencies: + - supports-color + optional: true + babel-plugin-polyfill-regenerator@0.6.8(@babel/core@7.29.7): dependencies: '@babel/core': 7.29.7 @@ -23740,6 +25227,14 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-polyfill-regenerator@0.6.8(@babel/core@8.0.1): + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@8.0.1) + transitivePeerDependencies: + - supports-color + optional: true + babel-plugin-react-native-web@0.19.13: {} babel-plugin-syntax-hermes-parser@0.23.1: @@ -23760,6 +25255,10 @@ snapshots: dependencies: '@babel/core': 7.29.7 + babel-plugin-transform-hook-names@1.0.2(@babel/core@8.0.1): + dependencies: + '@babel/core': 8.0.1 + babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.7): dependencies: '@babel/core': 7.29.7 @@ -23862,7 +25361,7 @@ snapshots: baseline-browser-mapping@2.10.13: {} - beasties@0.3.5: + beasties@0.4.3: dependencies: css-select: 6.0.0 css-what: 7.0.0 @@ -23872,6 +25371,7 @@ snapshots: picocolors: 1.1.1 postcss: 8.5.8 postcss-media-query-parser: 0.2.3 + postcss-safe-parser: 7.0.1(postcss@8.5.8) better-opn@3.0.2: dependencies: @@ -24144,19 +25644,6 @@ snapshots: tar: 6.2.1 unique-filename: 3.0.0 - cacache@20.0.4: - dependencies: - '@npmcli/fs': 5.0.0 - fs-minipass: 3.0.3 - glob: 13.0.6 - lru-cache: 11.2.7 - minipass: 7.1.3 - minipass-collect: 2.0.1 - minipass-flush: 1.0.7 - minipass-pipeline: 1.2.4 - p-map: 7.0.4 - ssri: 13.0.1 - cache-base@1.0.1: dependencies: collection-visit: 1.0.0 @@ -24368,16 +25855,18 @@ snapshots: cli-spinners@2.9.2: {} + cli-spinners@3.4.0: {} + cli-table3@0.6.5: dependencies: string-width: 4.2.3 optionalDependencies: '@colors/colors': 1.5.0 - cli-truncate@4.0.0: + cli-truncate@6.1.1: dependencies: - slice-ansi: 5.0.0 - string-width: 7.2.0 + slice-ansi: 9.0.0 + string-width: 8.2.2 cli-width@4.1.0: {} @@ -24419,6 +25908,8 @@ snapshots: cluster-key-slot@1.1.2: {} + code-block-writer@12.0.0: {} + collection-visit@1.0.0: dependencies: map-visit: 1.0.0 @@ -25199,9 +26690,9 @@ snapshots: entities@7.0.1: {} - env-editor@0.4.2: {} + entities@8.1.0: {} - env-paths@2.2.1: {} + env-editor@0.4.2: {} env-paths@4.0.0: dependencies: @@ -25211,8 +26702,6 @@ snapshots: environment@1.1.0: {} - err-code@2.0.3: {} - errno@0.1.8: dependencies: prr: 1.0.1 @@ -26053,8 +27542,18 @@ snapshots: fast-loops@1.1.4: {} + fast-string-truncated-width@3.0.3: {} + + fast-string-width@3.0.2: + dependencies: + fast-string-truncated-width: 3.0.3 + fast-uri@3.1.0: {} + fast-wrap-ansi@0.2.2: + dependencies: + fast-string-width: 3.0.2 + fastest-levenshtein@1.0.16: {} fastq@1.20.1: @@ -26717,16 +28216,16 @@ snapshots: hookable@6.1.1: {} + hosted-git-info@10.1.1: + dependencies: + lru-cache: 11.2.7 + hosted-git-info@2.8.9: {} hosted-git-info@7.0.2: dependencies: lru-cache: 10.4.3 - hosted-git-info@9.0.2: - dependencies: - lru-cache: 11.2.7 - html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 @@ -26844,6 +28343,15 @@ snapshots: transitivePeerDependencies: - supports-color + https-proxy-agent@9.1.0: + dependencies: + agent-base: 9.0.0 + debug: 4.4.3 + proxy-agent-negotiate: 1.1.0 + transitivePeerDependencies: + - kerberos + - supports-color + httpxy@0.3.1: {} human-id@4.1.3: {} @@ -26868,10 +28376,6 @@ snapshots: iferr@0.1.5: {} - ignore-walk@8.0.0: - dependencies: - minimatch: 10.2.5 - ignore@5.3.2: {} ignore@7.0.5: {} @@ -26924,8 +28428,6 @@ snapshots: ini@1.3.8: {} - ini@5.0.0: {} - ini@6.0.0: {} inline-style-prefixer@6.0.4: @@ -27063,8 +28565,6 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-fullwidth-code-point@4.0.0: {} - is-fullwidth-code-point@5.1.0: dependencies: get-east-asian-width: 1.5.0 @@ -27186,8 +28686,6 @@ snapshots: is-unicode-supported@0.1.0: {} - is-unicode-supported@1.3.0: {} - is-unicode-supported@2.1.0: {} is-weakmap@2.0.2: {} @@ -27229,8 +28727,6 @@ snapshots: isexe@3.1.5: {} - isexe@4.0.0: {} - isobject@2.1.0: dependencies: isarray: 1.0.0 @@ -27255,7 +28751,7 @@ snapshots: '@babel/parser': 7.29.8 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.7.4 + semver: 7.8.5 transitivePeerDependencies: - supports-color @@ -27410,7 +28906,7 @@ snapshots: jest-message-util: 30.3.0 jest-util: 30.3.0 pretty-format: 30.3.0 - semver: 7.7.4 + semver: 7.8.5 synckit: 0.11.12 transitivePeerDependencies: - supports-color @@ -27475,6 +28971,8 @@ snapshots: jose@6.2.2: {} + js-tokens@10.0.0: {} + js-tokens@4.0.0: {} js-tokens@9.0.1: {} @@ -27519,7 +29017,7 @@ snapshots: transitivePeerDependencies: - supports-color - jscodeshift@17.3.0(@babel/preset-env@7.29.2(@babel/core@7.29.7)): + jscodeshift@17.3.0(@babel/preset-env@7.29.2(@babel/core@8.0.1)): dependencies: '@babel/core': 7.29.7 '@babel/parser': 7.29.8 @@ -27540,7 +29038,7 @@ snapshots: tmp: 0.2.5 write-file-atomic: 5.0.1 optionalDependencies: - '@babel/preset-env': 7.29.2(@babel/core@7.29.7) + '@babel/preset-env': 7.29.2(@babel/core@8.0.1) transitivePeerDependencies: - supports-color @@ -27610,8 +29108,6 @@ snapshots: json-parse-even-better-errors@2.3.1: {} - json-parse-even-better-errors@5.0.0: {} - json-schema-traverse@0.4.1: {} json-schema-traverse@1.0.0: {} @@ -27642,8 +29138,6 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - jsonparse@1.3.1: {} - jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.9 @@ -27844,14 +29338,11 @@ snapshots: untun: 0.1.3 uqr: 0.1.2 - listr2@9.0.1: + listr2@11.0.0: dependencies: - cli-truncate: 4.0.0 - colorette: 2.0.20 - eventemitter3: 5.0.4 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 9.0.2 + cli-truncate: 6.1.1 + log-update: 8.0.0 + wrap-ansi: 10.0.1 lit-element@4.2.2: dependencies: @@ -27869,21 +29360,22 @@ snapshots: lit-element: 4.2.2 lit-html: 3.3.2 - lmdb@3.4.2: + lmdb@3.5.6: dependencies: + '@harperfast/extended-iterable': 1.0.3 msgpackr: 1.11.9 node-addon-api: 6.1.0 node-gyp-build-optional-packages: 5.2.2 ordered-binary: 1.6.1 weak-lru-cache: 1.2.2 optionalDependencies: - '@lmdb/lmdb-darwin-arm64': 3.4.2 - '@lmdb/lmdb-darwin-x64': 3.4.2 - '@lmdb/lmdb-linux-arm': 3.4.2 - '@lmdb/lmdb-linux-arm64': 3.4.2 - '@lmdb/lmdb-linux-x64': 3.4.2 - '@lmdb/lmdb-win32-arm64': 3.4.2 - '@lmdb/lmdb-win32-x64': 3.4.2 + '@lmdb/lmdb-darwin-arm64': 3.5.6 + '@lmdb/lmdb-darwin-x64': 3.5.6 + '@lmdb/lmdb-linux-arm': 3.5.6 + '@lmdb/lmdb-linux-arm64': 3.5.6 + '@lmdb/lmdb-linux-x64': 3.5.6 + '@lmdb/lmdb-win32-arm64': 3.5.6 + '@lmdb/lmdb-win32-x64': 3.5.6 optional: true loader-runner@2.4.0: {} @@ -27961,18 +29453,19 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 - log-symbols@6.0.0: + log-symbols@7.0.1: dependencies: - chalk: 5.6.2 - is-unicode-supported: 1.3.0 + is-unicode-supported: 2.1.0 + yoctocolors: 2.1.2 - log-update@6.1.0: + log-update@8.0.0: dependencies: ansi-escapes: 7.3.0 cli-cursor: 5.0.0 - slice-ansi: 7.1.2 + slice-ansi: 9.0.0 + string-width: 8.2.2 strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 + wrap-ansi: 10.0.1 longest-streak@3.1.0: {} @@ -28000,11 +29493,11 @@ snapshots: lz-string@1.5.0: {} - magic-string@0.30.17: + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magic-string@0.30.21: + magic-string@1.0.0: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -28039,23 +29532,6 @@ snapshots: dependencies: semver: 7.7.4 - make-fetch-happen@15.0.5: - dependencies: - '@gar/promise-retry': 1.0.3 - '@npmcli/agent': 4.0.0 - '@npmcli/redact': 4.0.0 - cacache: 20.0.4 - http-cache-semantics: 4.2.0 - minipass: 7.1.3 - minipass-fetch: 5.0.2 - minipass-flush: 1.0.7 - minipass-pipeline: 1.2.4 - negotiator: 1.0.0 - proc-log: 6.1.0 - ssri: 13.0.1 - transitivePeerDependencies: - - supports-color - makeerror@1.0.12: dependencies: tmpl: 1.0.5 @@ -28735,14 +30211,6 @@ snapshots: dependencies: minipass: 7.1.3 - minipass-fetch@5.0.2: - dependencies: - minipass: 7.1.3 - minipass-sized: 2.0.0 - minizlib: 3.1.0 - optionalDependencies: - iconv-lite: 0.7.2 - minipass-flush@1.0.7: dependencies: minipass: 3.3.6 @@ -28751,10 +30219,6 @@ snapshots: dependencies: minipass: 3.3.6 - minipass-sized@2.0.0: - dependencies: - minipass: 7.1.3 - minipass@3.3.6: dependencies: yallist: 4.0.0 @@ -28796,6 +30260,8 @@ snapshots: mkdirp@1.0.4: {} + mkdirp@3.0.1: {} + mlly@1.8.2: dependencies: acorn: 8.16.0 @@ -28944,6 +30410,8 @@ snapshots: mute-stream@2.0.0: {} + mute-stream@3.0.0: {} + mz@2.7.0: dependencies: any-promise: 1.3.0 @@ -28992,7 +30460,7 @@ snapshots: nested-error-stacks@2.1.1: {} - next@14.2.35(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.90.0): + next@14.2.35(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.101.0): dependencies: '@next/env': 14.2.35 '@swc/helpers': 0.5.5 @@ -29013,12 +30481,12 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.2.33 '@next/swc-win32-ia32-msvc': 14.2.33 '@next/swc-win32-x64-msvc': 14.2.33 - sass: 1.90.0 + sass: 1.101.0 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - next@15.5.14(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0): + next@15.5.14(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0): dependencies: '@next/env': 15.5.14 '@swc/helpers': 0.5.15 @@ -29036,13 +30504,13 @@ snapshots: '@next/swc-linux-x64-musl': 15.5.14 '@next/swc-win32-arm64-msvc': 15.5.14 '@next/swc-win32-x64-msvc': 15.5.14 - sass: 1.90.0 + sass: 1.101.0 sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - next@16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.90.0): + next@16.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.101.0): dependencies: '@next/env': 16.2.2 '@swc/helpers': 0.5.15 @@ -29061,7 +30529,7 @@ snapshots: '@next/swc-linux-x64-musl': 16.2.2 '@next/swc-win32-arm64-msvc': 16.2.2 '@next/swc-win32-x64-msvc': 16.2.2 - sass: 1.90.0 + sass: 1.101.0 sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' @@ -29069,7 +30537,7 @@ snapshots: nice-try@1.0.5: {} - nitropack@2.13.2(@vercel/functions@2.2.13)(idb-keyval@6.2.2)(rolldown@1.2.4)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)): + nitropack@2.13.2(@vercel/functions@2.2.13)(idb-keyval@6.2.2)(rolldown@1.2.4)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)): dependencies: '@cloudflare/kv-asset-handler': 0.4.2 '@rollup/plugin-alias': 6.0.0(rollup@4.60.1) @@ -29134,7 +30602,7 @@ snapshots: uncrypto: 0.1.3 unctx: 2.5.0 unenv: 2.0.0-rc.24 - unimport: 6.0.2(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) + unimport: 6.0.2(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) unplugin-utils: 0.3.1 unstorage: 1.17.5(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1) untyped: 2.0.0 @@ -29233,21 +30701,6 @@ snapshots: node-gyp-build@4.8.4: {} - node-gyp@12.2.0: - dependencies: - env-paths: 2.2.1 - exponential-backoff: 3.1.3 - graceful-fs: 4.2.11 - make-fetch-happen: 15.0.5 - nopt: 9.0.0 - proc-log: 6.1.0 - semver: 7.7.4 - tar: 7.5.13 - tinyglobby: 0.2.17 - which: 6.0.1 - transitivePeerDependencies: - - supports-color - node-html-parser@6.1.13: dependencies: css-select: 5.2.2 @@ -29291,10 +30744,6 @@ snapshots: dependencies: abbrev: 3.0.1 - nopt@9.0.0: - dependencies: - abbrev: 4.0.0 - normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 @@ -29304,16 +30753,6 @@ snapshots: normalize-path@3.0.0: {} - npm-bundled@5.0.0: - dependencies: - npm-normalize-package-bin: 5.0.0 - - npm-install-checks@8.0.0: - dependencies: - semver: 7.7.4 - - npm-normalize-package-bin@5.0.0: {} - npm-package-arg@11.0.3: dependencies: hosted-git-info: 7.0.2 @@ -29321,37 +30760,12 @@ snapshots: semver: 7.7.4 validate-npm-package-name: 5.0.1 - npm-package-arg@13.0.0: - dependencies: - hosted-git-info: 9.0.2 - proc-log: 5.0.0 - semver: 7.7.4 - validate-npm-package-name: 6.0.2 - - npm-packlist@10.0.4: - dependencies: - ignore-walk: 8.0.0 - proc-log: 6.1.0 - - npm-pick-manifest@11.0.3: + npm-package-arg@14.0.0: dependencies: - npm-install-checks: 8.0.0 - npm-normalize-package-bin: 5.0.0 - npm-package-arg: 13.0.0 + hosted-git-info: 10.1.1 + proc-log: 7.0.0 semver: 7.7.4 - - npm-registry-fetch@19.1.1: - dependencies: - '@npmcli/redact': 4.0.0 - jsonparse: 1.3.1 - make-fetch-happen: 15.0.5 - minipass: 7.1.3 - minipass-fetch: 5.0.2 - minizlib: 3.1.0 - npm-package-arg: 13.0.0 - proc-log: 6.1.0 - transitivePeerDependencies: - - supports-color + validate-npm-package-name: 8.0.0 npm-run-all2@5.0.2: dependencies: @@ -29618,17 +31032,16 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 - ora@8.2.0: + ora@9.4.1: dependencies: chalk: 5.6.2 cli-cursor: 5.0.0 - cli-spinners: 2.9.2 + cli-spinners: 3.4.0 is-interactive: 2.0.0 is-unicode-supported: 2.1.0 - log-symbols: 6.0.0 - stdin-discarder: 0.2.2 - string-width: 7.2.0 - strip-ansi: 7.2.0 + log-symbols: 7.0.1 + stdin-discarder: 0.3.2 + string-width: 8.2.2 ordered-binary@1.6.1: optional: true @@ -29645,6 +31058,59 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 + oxc-parser@0.121.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2): + dependencies: + '@oxc-project/types': 0.121.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.121.0 + '@oxc-parser/binding-android-arm64': 0.121.0 + '@oxc-parser/binding-darwin-arm64': 0.121.0 + '@oxc-parser/binding-darwin-x64': 0.121.0 + '@oxc-parser/binding-freebsd-x64': 0.121.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.121.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.121.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.121.0 + '@oxc-parser/binding-linux-arm64-musl': 0.121.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.121.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.121.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.121.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.121.0 + '@oxc-parser/binding-linux-x64-gnu': 0.121.0 + '@oxc-parser/binding-linux-x64-musl': 0.121.0 + '@oxc-parser/binding-openharmony-arm64': 0.121.0 + '@oxc-parser/binding-wasm32-wasi': 0.121.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@oxc-parser/binding-win32-arm64-msvc': 0.121.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.121.0 + '@oxc-parser/binding-win32-x64-msvc': 0.121.0 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + oxc-parser@0.142.0: + dependencies: + '@oxc-project/types': 0.142.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.142.0 + '@oxc-parser/binding-android-arm64': 0.142.0 + '@oxc-parser/binding-darwin-arm64': 0.142.0 + '@oxc-parser/binding-darwin-x64': 0.142.0 + '@oxc-parser/binding-freebsd-x64': 0.142.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.142.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.142.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.142.0 + '@oxc-parser/binding-linux-arm64-musl': 0.142.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.142.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.142.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.142.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.142.0 + '@oxc-parser/binding-linux-x64-gnu': 0.142.0 + '@oxc-parser/binding-linux-x64-musl': 0.142.0 + '@oxc-parser/binding-openharmony-arm64': 0.142.0 + '@oxc-parser/binding-wasm32-wasi': 0.142.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.142.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.142.0 + '@oxc-parser/binding-win32-x64-msvc': 0.142.0 + oxc-parser@0.143.0: dependencies: '@oxc-project/types': 0.143.0 @@ -29749,8 +31215,6 @@ snapshots: p-map@6.0.0: {} - p-map@7.0.4: {} - p-queue@6.6.2: dependencies: eventemitter3: 4.0.7 @@ -29779,28 +31243,6 @@ snapshots: package-manager-detector@1.6.0: {} - pacote@21.0.4: - dependencies: - '@npmcli/git': 7.0.2 - '@npmcli/installed-package-contents': 4.0.0 - '@npmcli/package-json': 7.0.5 - '@npmcli/promise-spawn': 9.0.1 - '@npmcli/run-script': 10.0.4 - cacache: 20.0.4 - fs-minipass: 3.0.3 - minipass: 7.1.3 - npm-package-arg: 13.0.0 - npm-packlist: 10.0.4 - npm-pick-manifest: 11.0.3 - npm-registry-fetch: 19.1.1 - proc-log: 6.1.0 - promise-retry: 2.0.1 - sigstore: 4.1.0 - ssri: 13.0.1 - tar: 7.5.13 - transitivePeerDependencies: - - supports-color - pako@1.0.11: {} parallel-transform@1.2.0: @@ -29861,9 +31303,9 @@ snapshots: parse-statements@1.0.11: {} - parse5-html-rewriting-stream@8.0.0: + parse5-html-rewriting-stream@8.0.1: dependencies: - entities: 6.0.1 + entities: 8.1.0 parse5: 8.0.0 parse5-sax-parser: 8.0.0 @@ -29968,8 +31410,6 @@ snapshots: picomatch@3.0.2: {} - picomatch@4.0.4: {} - picomatch@4.0.5: {} pidtree@0.5.0: {} @@ -29980,7 +31420,7 @@ snapshots: pirates@4.0.7: {} - piscina@5.1.3: + piscina@5.2.0: optionalDependencies: '@napi-rs/nice': 1.1.1 @@ -30159,9 +31599,7 @@ snapshots: proc-log@4.2.0: {} - proc-log@5.0.0: {} - - proc-log@6.1.0: {} + proc-log@7.0.0: {} process-nextick-args@2.0.1: {} @@ -30173,11 +31611,6 @@ snapshots: optionalDependencies: bluebird: 3.7.2 - promise-retry@2.0.1: - dependencies: - err-code: 2.0.3 - retry: 0.12.0 - promise@7.3.1: dependencies: asap: 2.0.6 @@ -30204,6 +31637,8 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-agent-negotiate@1.1.0: {} + proxy-from-env@2.1.0: {} prr@1.0.1: {} @@ -30791,12 +32226,6 @@ snapshots: resolve.exports@2.0.3: {} - resolve@1.22.10: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - resolve@1.22.11: dependencies: is-core-module: 2.16.1 @@ -30858,14 +32287,10 @@ snapshots: retext-stringify: 4.0.0 unified: 11.0.5 - retry@0.12.0: {} - rettime@0.10.1: {} reusify@1.1.0: {} - rfdc@1.4.1: {} - rimraf@2.6.3: dependencies: glob: 7.2.3 @@ -30898,6 +32323,27 @@ snapshots: transitivePeerDependencies: - oxc-resolver + rolldown@1.2.0: + dependencies: + '@oxc-project/types': 0.140.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.2.0 + '@rolldown/binding-darwin-arm64': 1.2.0 + '@rolldown/binding-darwin-x64': 1.2.0 + '@rolldown/binding-freebsd-x64': 1.2.0 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.0 + '@rolldown/binding-linux-arm64-gnu': 1.2.0 + '@rolldown/binding-linux-arm64-musl': 1.2.0 + '@rolldown/binding-linux-ppc64-gnu': 1.2.0 + '@rolldown/binding-linux-s390x-gnu': 1.2.0 + '@rolldown/binding-linux-x64-gnu': 1.2.0 + '@rolldown/binding-linux-x64-musl': 1.2.0 + '@rolldown/binding-openharmony-arm64': 1.2.0 + '@rolldown/binding-wasm32-wasi': 1.2.0 + '@rolldown/binding-win32-arm64-msvc': 1.2.0 + '@rolldown/binding-win32-x64-msvc': 1.2.0 + rolldown@1.2.4: dependencies: '@oxc-project/types': 0.144.0 @@ -30934,37 +32380,6 @@ snapshots: rolldown: 1.2.4 rollup: 4.60.1 - rollup@4.59.0: - dependencies: - '@types/estree': 1.0.8 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.59.0 - '@rollup/rollup-android-arm64': 4.59.0 - '@rollup/rollup-darwin-arm64': 4.59.0 - '@rollup/rollup-darwin-x64': 4.59.0 - '@rollup/rollup-freebsd-arm64': 4.59.0 - '@rollup/rollup-freebsd-x64': 4.59.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 - '@rollup/rollup-linux-arm-musleabihf': 4.59.0 - '@rollup/rollup-linux-arm64-gnu': 4.59.0 - '@rollup/rollup-linux-arm64-musl': 4.59.0 - '@rollup/rollup-linux-loong64-gnu': 4.59.0 - '@rollup/rollup-linux-loong64-musl': 4.59.0 - '@rollup/rollup-linux-ppc64-gnu': 4.59.0 - '@rollup/rollup-linux-ppc64-musl': 4.59.0 - '@rollup/rollup-linux-riscv64-gnu': 4.59.0 - '@rollup/rollup-linux-riscv64-musl': 4.59.0 - '@rollup/rollup-linux-s390x-gnu': 4.59.0 - '@rollup/rollup-linux-x64-gnu': 4.59.0 - '@rollup/rollup-linux-x64-musl': 4.59.0 - '@rollup/rollup-openbsd-x64': 4.59.0 - '@rollup/rollup-openharmony-arm64': 4.59.0 - '@rollup/rollup-win32-arm64-msvc': 4.59.0 - '@rollup/rollup-win32-ia32-msvc': 4.59.0 - '@rollup/rollup-win32-x64-gnu': 4.59.0 - '@rollup/rollup-win32-x64-msvc': 4.59.0 - fsevents: 2.3.3 - rollup@4.60.1: dependencies: '@types/estree': 1.0.8 @@ -31066,7 +32481,7 @@ snapshots: safer-buffer@2.1.2: {} - sass@1.90.0: + sass@1.101.0: dependencies: chokidar: 5.0.0 immutable: 5.1.5 @@ -31105,9 +32520,9 @@ snapshots: schema-utils@4.3.3: dependencies: '@types/json-schema': 7.0.15 - ajv: 8.18.0 - ajv-formats: 2.1.1(ajv@8.18.0) - ajv-keywords: 5.1.0(ajv@8.18.0) + ajv: 8.20.0 + ajv-formats: 2.1.1(ajv@8.20.0) + ajv-keywords: 5.1.0(ajv@8.20.0) scule@1.3.0: {} @@ -31124,10 +32539,10 @@ snapshots: dependencies: lru-cache: 6.0.0 - semver@7.7.2: {} - semver@7.7.4: {} + semver@7.8.5: {} + send@0.19.2: dependencies: debug: 2.6.9 @@ -31382,17 +32797,6 @@ snapshots: signal-exit@4.1.0: {} - sigstore@4.1.0: - dependencies: - '@sigstore/bundle': 4.0.0 - '@sigstore/core': 3.2.0 - '@sigstore/protobuf-specs': 0.5.0 - '@sigstore/sign': 4.1.1 - '@sigstore/tuf': 4.0.2 - '@sigstore/verify': 3.1.0 - transitivePeerDependencies: - - supports-color - simple-code-frame@1.3.0: dependencies: kolorist: 1.8.0 @@ -31435,20 +32839,13 @@ snapshots: slash@5.1.0: {} - slice-ansi@5.0.0: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 4.0.0 - - slice-ansi@7.1.2: + slice-ansi@9.0.0: dependencies: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 slugify@1.6.8: {} - smart-buffer@4.2.0: {} - smob@1.6.1: {} smol-toml@1.8.0: {} @@ -31476,19 +32873,6 @@ snapshots: transitivePeerDependencies: - supports-color - socks-proxy-agent@8.0.5: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - socks: 2.8.7 - transitivePeerDependencies: - - supports-color - - socks@2.8.7: - dependencies: - ip-address: 10.1.0 - smart-buffer: 4.2.0 - solid-js@1.9.12: dependencies: csstype: 3.2.3 @@ -31597,10 +32981,6 @@ snapshots: dependencies: minipass: 7.1.3 - ssri@13.0.1: - dependencies: - minipass: 7.1.3 - ssri@6.0.2: dependencies: figgy-pudding: 3.5.2 @@ -31636,7 +33016,7 @@ snapshots: std-env@4.0.0: {} - stdin-discarder@0.2.2: {} + stdin-discarder@0.3.2: {} stop-iteration-iterator@1.1.0: dependencies: @@ -31702,6 +33082,11 @@ snapshots: get-east-asian-width: 1.5.0 strip-ansi: 7.2.0 + string-width@8.2.2: + dependencies: + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + string.prototype.matchall@4.0.12: dependencies: call-bind: 1.0.8 @@ -32131,11 +33516,6 @@ snapshots: tinyexec@1.3.0: {} - tinyglobby@0.2.14: - dependencies: - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 - tinyglobby@0.2.17: dependencies: fdir: 6.5.0(picomatch@4.0.5) @@ -32241,12 +33621,21 @@ snapshots: ts-interface-checker@0.1.13: {} + ts-morph@21.0.1: + dependencies: + '@ts-morph/common': 0.22.0 + code-block-writer: 12.0.0 + ts-pattern@5.9.0: {} tsconfck@3.1.6(typescript@5.8.3): optionalDependencies: typescript: 5.8.3 + tsconfck@3.1.6(typescript@5.9.3): + optionalDependencies: + typescript: 5.9.3 + tsconfck@3.1.6(typescript@6.0.3): optionalDependencies: typescript: 6.0.3 @@ -32295,14 +33684,6 @@ snapshots: tty-browserify@0.0.0: {} - tuf-js@4.1.0: - dependencies: - '@tufjs/models': 4.1.0 - debug: 4.4.3 - make-fetch-happen: 15.0.5 - transitivePeerDependencies: - - supports-color - tupleson@0.23.1: {} type-check@0.4.0: @@ -32531,7 +33912,7 @@ snapshots: ofetch: 1.5.1 ohash: 2.0.11 - unimport@6.0.2(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)): + unimport@6.0.2(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)): dependencies: acorn: 8.16.0 escape-string-regexp: 5.0.0 @@ -32545,7 +33926,7 @@ snapshots: scule: 1.3.0 strip-literal: 3.1.0 tinyglobby: 0.2.17 - unplugin: 3.3.0(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) + unplugin: 3.3.0(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) unplugin-utils: 0.3.1 transitivePeerDependencies: - '@farmfe/core' @@ -32637,18 +34018,18 @@ snapshots: unpipe@1.0.0: {} - unplugin-solid@2.0.0(@testing-library/jest-dom@6.9.1)(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)): + unplugin-solid@2.0.0(@testing-library/jest-dom@6.9.1)(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)): dependencies: '@babel/core': 7.29.7 babel-preset-solid: 1.9.12(@babel/core@7.29.7)(solid-js@1.9.12) merge-anything: 6.0.6 solid-js: 1.9.12 solid-refresh: 0.7.8(solid-js@1.9.12) - unplugin: 3.3.0(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) - vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + unplugin: 3.3.0(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) + vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) optionalDependencies: '@testing-library/jest-dom': 6.9.1 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) transitivePeerDependencies: - '@farmfe/core' - '@rspack/core' @@ -32672,7 +34053,7 @@ snapshots: picomatch: 4.0.5 webpack-virtual-modules: 0.6.2 - unplugin@3.3.0(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)): + unplugin@3.3.0(esbuild@0.27.4)(rolldown@1.2.4)(rollup@4.60.1)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)): dependencies: '@jridgewell/remapping': 2.3.5 picomatch: 4.0.5 @@ -32681,7 +34062,7 @@ snapshots: esbuild: 0.27.4 rolldown: 1.2.4 rollup: 4.60.1 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) webpack: 5.105.4(esbuild@0.27.4) unrs-resolver@1.11.1: @@ -32813,7 +34194,7 @@ snapshots: validate-npm-package-name@5.0.1: {} - validate-npm-package-name@6.0.2: {} + validate-npm-package-name@8.0.0: {} vary@1.1.2: {} @@ -32834,7 +34215,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0): + vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rolldown@1.2.4)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(webpack@5.105.4(esbuild@0.27.4))(yaml@2.9.0): dependencies: '@babel/core': 7.29.7 '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.7) @@ -32855,7 +34236,7 @@ snapshots: hookable: 5.5.3 http-proxy: 1.18.1 micromatch: 4.0.8 - nitropack: 2.13.2(@vercel/functions@2.2.13)(idb-keyval@6.2.2)(rolldown@1.2.4)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) + nitropack: 2.13.2(@vercel/functions@2.2.13)(idb-keyval@6.2.2)(rolldown@1.2.4)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))(webpack@5.105.4(esbuild@0.27.4)) node-fetch-native: 1.6.7 path-to-regexp: 6.3.0 pathe: 1.1.2 @@ -32868,7 +34249,7 @@ snapshots: unctx: 2.5.0 unenv: 1.10.0 unstorage: 1.17.5(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1) - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) zod: 4.4.3 transitivePeerDependencies: - '@azure/app-configuration' @@ -32921,7 +34302,26 @@ snapshots: - xml2js - yaml - vite-plugin-dts@4.2.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-plugin-dts@4.2.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + dependencies: + '@microsoft/api-extractor': 7.47.7(@types/node@22.19.15) + '@rollup/pluginutils': 5.3.0(rollup@4.60.1) + '@volar/typescript': 2.4.28 + '@vue/language-core': 2.1.6(typescript@5.9.3) + compare-versions: 6.1.1 + debug: 4.4.3 + kolorist: 1.8.0 + local-pkg: 0.5.1 + magic-string: 0.30.21 + typescript: 5.9.3 + optionalDependencies: + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + + vite-plugin-dts@4.2.3(@types/node@22.19.15)(rollup@4.60.1)(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): dependencies: '@microsoft/api-extractor': 7.47.7(@types/node@22.19.15) '@rollup/pluginutils': 5.3.0(rollup@4.60.1) @@ -32934,21 +34334,21 @@ snapshots: magic-string: 0.30.21 typescript: 6.0.3 optionalDependencies: - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite-plugin-externalize-deps@0.10.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-plugin-externalize-deps@0.10.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): dependencies: - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vite-plugin-externalize-deps@0.9.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-plugin-externalize-deps@0.9.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): dependencies: - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vite-plugin-solid@2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-plugin-solid@2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): dependencies: '@babel/core': 7.29.7 '@types/babel__core': 7.20.5 @@ -32956,14 +34356,14 @@ snapshots: merge-anything: 5.1.7 solid-js: 1.9.12 solid-refresh: 0.6.3(solid-js@1.9.12) - vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) optionalDependencies: '@testing-library/jest-dom': 6.9.1 transitivePeerDependencies: - supports-color - vite-plugin-solid@2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-plugin-solid@2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): dependencies: '@babel/core': 7.29.7 '@types/babel__core': 7.20.5 @@ -32971,14 +34371,14 @@ snapshots: merge-anything: 5.1.7 solid-js: 1.9.12 solid-refresh: 0.6.3(solid-js@1.9.12) - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vitefu: 1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) optionalDependencies: '@testing-library/jest-dom': 6.9.1 transitivePeerDependencies: - supports-color - vite-prerender-plugin@0.5.13(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-prerender-plugin@0.5.13(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): dependencies: kolorist: 1.8.0 magic-string: 0.30.21 @@ -32986,20 +34386,31 @@ snapshots: simple-code-frame: 1.3.0 source-map: 0.7.6 stack-trace: 1.0.0-pre2 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + + vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + dependencies: + debug: 4.4.3 + globrex: 0.1.2 + tsconfck: 3.1.6(typescript@5.9.3) + optionalDependencies: + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + transitivePeerDependencies: + - supports-color + - typescript - vite-tsconfig-paths@5.1.4(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-tsconfig-paths@5.1.4(typescript@6.0.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): dependencies: debug: 4.4.3 globrex: 0.1.2 tsconfck: 3.1.6(typescript@6.0.3) optionalDependencies: - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) transitivePeerDependencies: - supports-color - typescript - vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0): + vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0): dependencies: esbuild: 0.27.4 fdir: 6.5.0(picomatch@4.0.5) @@ -33012,12 +34423,12 @@ snapshots: fsevents: 2.3.3 jiti: 1.21.7 lightningcss: 1.32.0 - sass: 1.90.0 + sass: 1.101.0 terser: 5.46.1 tsx: 4.21.0 yaml: 2.9.0 - vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0): + vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0): dependencies: esbuild: 0.27.4 fdir: 6.5.0(picomatch@4.0.5) @@ -33030,23 +34441,41 @@ snapshots: fsevents: 2.3.3 jiti: 2.7.0 lightningcss: 1.32.0 - sass: 1.90.0 + sass: 1.101.0 terser: 5.46.1 tsx: 4.21.0 yaml: 2.9.0 - vitefu@1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vite@7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0): + dependencies: + esbuild: 0.27.4 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + postcss: 8.5.8 + rollup: 4.60.1 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 22.19.15 + fsevents: 2.3.3 + jiti: 2.7.0 + lightningcss: 1.32.0 + sass: 1.101.0 + terser: 5.46.1 + tsx: 4.21.0 + yaml: 2.9.0 + + vitefu@1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): optionalDependencies: - vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu@1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vitefu@1.1.3(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): optionalDependencies: - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.2 - '@vitest/mocker': 4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@vitest/mocker': 4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.2 '@vitest/runner': 4.1.2 '@vitest/snapshot': 4.1.2 @@ -33063,19 +34492,46 @@ snapshots: tinyexec: 1.3.0 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.19.15 + jsdom: 27.4.0 + transitivePeerDependencies: + - msw + + vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + dependencies: + '@vitest/expect': 4.1.2 + '@vitest/mocker': 4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.2 + '@vitest/runner': 4.1.2 + '@vitest/snapshot': 4.1.2 + '@vitest/spy': 4.1.2 + '@vitest/utils': 4.1.2 + es-module-lexer: 2.0.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.4 + pathe: 2.0.3 + picomatch: 4.0.5 + std-env: 4.0.0 + tinybench: 2.9.0 + tinyexec: 1.3.0 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.19.15 jsdom: 27.4.0 transitivePeerDependencies: - msw - optional: true - vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.2 - '@vitest/mocker': 4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@vitest/mocker': 4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@6.0.3))(vite@7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.2 '@vitest/runner': 4.1.2 '@vitest/snapshot': 4.1.2 @@ -33092,18 +34548,19 @@ snapshots: tinyexec: 1.3.0 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.1.11(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.19.15 jsdom: 27.4.0 transitivePeerDependencies: - msw + optional: true - vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@7.0.2))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): + vitest@4.1.2(@types/node@22.19.15)(jsdom@27.4.0)(msw@2.12.14(@types/node@22.19.15)(typescript@7.0.2))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.2 - '@vitest/mocker': 4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@7.0.2))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) + '@vitest/mocker': 4.1.2(msw@2.12.14(@types/node@22.19.15)(typescript@7.0.2))(vite@6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.2 '@vitest/runner': 4.1.2 '@vitest/snapshot': 4.1.2 @@ -33120,7 +34577,7 @@ snapshots: tinyexec: 1.3.0 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.19.15 @@ -33243,7 +34700,7 @@ snapshots: eslint-visitor-keys: 5.0.1 espree: 11.2.0 esquery: 1.7.0 - semver: 7.7.4 + semver: 7.8.5 transitivePeerDependencies: - supports-color @@ -33305,14 +34762,8 @@ snapshots: chokidar: 5.0.0 watchpack-chokidar2: 2.0.1 - watchpack@2.4.4: - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - - watchpack@2.5.1: + watchpack@2.5.2: dependencies: - glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 wcwidth@1.0.1: @@ -33437,7 +34888,7 @@ snapshots: schema-utils: 4.3.3 tapable: 2.3.2 terser-webpack-plugin: 5.4.0(esbuild@0.27.4)(webpack@5.105.4(esbuild@0.27.4)) - watchpack: 2.5.1 + watchpack: 2.5.2 webpack-sources: 3.3.4 transitivePeerDependencies: - '@swc/core' @@ -33470,7 +34921,7 @@ snapshots: schema-utils: 4.3.3 tapable: 2.3.2 terser-webpack-plugin: 5.4.0(webpack@5.105.4) - watchpack: 2.5.1 + watchpack: 2.5.2 webpack-sources: 3.3.4 optionalDependencies: webpack-cli: 5.1.4(webpack@5.105.4) @@ -33565,10 +35016,6 @@ snapshots: dependencies: isexe: 3.1.5 - which@6.0.1: - dependencies: - isexe: 4.0.0 - why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 @@ -33588,6 +35035,11 @@ snapshots: dependencies: errno: 0.1.8 + wrap-ansi@10.0.1: + dependencies: + ansi-styles: 6.2.3 + string-width: 8.2.2 + wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 @@ -33650,6 +35102,8 @@ snapshots: xdg-basedir@5.1.0: {} + xhr2@0.2.1: {} + xml-name-validator@4.0.0: {} xml-name-validator@5.0.0: {} @@ -33736,6 +35190,15 @@ snapshots: y18n: 5.0.8 yargs-parser: 22.0.0 + yargs@18.1.0: + dependencies: + cliui: 9.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + string-width: 8.2.2 + y18n: 5.0.8 + yargs-parser: 22.0.0 + yocto-queue@0.1.0: {} yocto-queue@1.2.2: {} @@ -33812,9 +35275,9 @@ snapshots: dependencies: zod: 3.25.76 - zod-to-json-schema@3.25.2(zod@4.1.13): + zod-to-json-schema@3.25.2(zod@4.4.3): dependencies: - zod: 4.1.13 + zod: 4.4.3 zod-to-ts@1.2.0(typescript@5.8.3)(zod@3.25.76): dependencies: @@ -33827,10 +35290,8 @@ snapshots: zod@3.25.76: {} - zod@4.1.13: {} - zod@4.4.3: {} - zone.js@0.15.0: {} + zone.js@0.16.1: {} zwitch@2.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4e37d863ded..a2b08110a9c 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -25,6 +25,7 @@ packages: - '!examples/vue/nuxt*' overrides: + '@inquirer/external-editor': '3.0.5' 'chokidar': '5.0.0' '@types/react': '^19.2.7' '@types/react-dom': '^19.2.3' @@ -42,6 +43,7 @@ overrides: '@typescript-eslint/visitor-keys': '8.58.1' typescript-eslint: '8.58.1' vite: '^6.4.1' + '@angular/build@22.1.8>vite': '7.1.11' esbuild: '^0.27.2' allowBuilds: diff --git a/scripts/generate-docs.ts b/scripts/generate-docs.ts index c467308652e..e2d5cd8d74e 100644 --- a/scripts/generate-docs.ts +++ b/scripts/generate-docs.ts @@ -214,11 +214,11 @@ async function generatePackageReferenceDocs(pkg: PackageReferenceDocsConfig) { const packages: Array = [ { entryPoints: [ - resolve(__dirname, '../packages/angular-query-experimental/src/index.ts'), + resolve(__dirname, '../packages/angular-query/src/index.ts'), ], tsconfig: resolve( __dirname, - '../packages/angular-query-experimental/tsconfig.json', + '../packages/angular-query/tsconfig.json', ), outputDir: resolve(__dirname, '../docs/framework/angular/reference'), }, From 4d78eec426feda621897872dec7b62772b410296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Wed, 16 Sep 2026 19:24:16 -0300 Subject: [PATCH 2/9] chore(angular): clean prerelease changesets and rename CLI integration --- .changeset/angular-20-ssr-lazy-signals.md | 7 ------- .changeset/angular-devtools-theme.md | 5 ----- .changeset/angular-effect-subscriptions.md | 5 ----- .changeset/angular-restoration-factory.md | 10 ---------- .changeset/angular-ssr-zone-timers.md | 5 ----- .changeset/angular-stable-release.md | 4 +--- .changeset/angular-store-zone-boundary.md | 5 ----- .changeset/persist-inject-factory.md | 5 ----- .changeset/reactive-devtools-options.md | 7 ------- .../{angular-cli-20 => angular-cli}/.gitignore | 0 .../.vscode/extensions.json | 0 .../.vscode/launch.json | 0 .../.vscode/tasks.json | 0 .../{angular-cli-20 => angular-cli}/README.md | 4 ++-- .../{angular-cli-20 => angular-cli}/angular.json | 6 +++--- .../{angular-cli-20 => angular-cli}/package.json | 2 +- .../public/favicon.ico | Bin .../src/app/app.config.ts | 0 .../{angular-cli-20 => angular-cli}/src/app/app.ts | 0 .../{angular-cli-20 => angular-cli}/src/index.html | 2 +- .../{angular-cli-20 => angular-cli}/src/main.ts | 0 .../{angular-cli-20 => angular-cli}/src/styles.css | 0 .../tsconfig.app.json | 0 .../{angular-cli-20 => angular-cli}/tsconfig.json | 0 pnpm-lock.yaml | 2 +- 25 files changed, 9 insertions(+), 60 deletions(-) delete mode 100644 .changeset/angular-20-ssr-lazy-signals.md delete mode 100644 .changeset/angular-devtools-theme.md delete mode 100644 .changeset/angular-effect-subscriptions.md delete mode 100644 .changeset/angular-restoration-factory.md delete mode 100644 .changeset/angular-ssr-zone-timers.md delete mode 100644 .changeset/angular-store-zone-boundary.md delete mode 100644 .changeset/persist-inject-factory.md delete mode 100644 .changeset/reactive-devtools-options.md rename integrations/{angular-cli-20 => angular-cli}/.gitignore (100%) rename integrations/{angular-cli-20 => angular-cli}/.vscode/extensions.json (100%) rename integrations/{angular-cli-20 => angular-cli}/.vscode/launch.json (100%) rename integrations/{angular-cli-20 => angular-cli}/.vscode/tasks.json (100%) rename integrations/{angular-cli-20 => angular-cli}/README.md (96%) rename integrations/{angular-cli-20 => angular-cli}/angular.json (94%) rename integrations/{angular-cli-20 => angular-cli}/package.json (96%) rename integrations/{angular-cli-20 => angular-cli}/public/favicon.ico (100%) rename integrations/{angular-cli-20 => angular-cli}/src/app/app.config.ts (100%) rename integrations/{angular-cli-20 => angular-cli}/src/app/app.ts (100%) rename integrations/{angular-cli-20 => angular-cli}/src/index.html (90%) rename integrations/{angular-cli-20 => angular-cli}/src/main.ts (100%) rename integrations/{angular-cli-20 => angular-cli}/src/styles.css (100%) rename integrations/{angular-cli-20 => angular-cli}/tsconfig.app.json (100%) rename integrations/{angular-cli-20 => angular-cli}/tsconfig.json (100%) diff --git a/.changeset/angular-20-ssr-lazy-signals.md b/.changeset/angular-20-ssr-lazy-signals.md deleted file mode 100644 index 1b0c09dce13..00000000000 --- a/.changeset/angular-20-ssr-lazy-signals.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@tanstack/angular-query': minor ---- - -Angular 20 update, SSR support (hydration controls and TransferState), and lazy signal initialization for the Angular adapter. - -Reduce production bundle overhead with removable result-field enumeration, a tuple return from the internal base-query helper, and development guards around query and mutation injection-context assertions. diff --git a/.changeset/angular-devtools-theme.md b/.changeset/angular-devtools-theme.md deleted file mode 100644 index 3a6a6d7072b..00000000000 --- a/.changeset/angular-devtools-theme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tanstack/angular-query-devtools': patch ---- - -Restore the reactive `theme` option in Angular Query devtools. diff --git a/.changeset/angular-effect-subscriptions.md b/.changeset/angular-effect-subscriptions.md deleted file mode 100644 index a93bd569520..00000000000 --- a/.changeset/angular-effect-subscriptions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tanstack/angular-query': patch ---- - -Manage external-store subscriptions through Angular's lifecycle, keeping snapshot reads free of subscription side effects. Catch changes made during initialization and source replacement, preserve synchronous notifications once connected, and clean up on destruction. Public signatures are unchanged. diff --git a/.changeset/angular-restoration-factory.md b/.changeset/angular-restoration-factory.md deleted file mode 100644 index d5e5cd64859..00000000000 --- a/.changeset/angular-restoration-factory.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@tanstack/angular-query': major -'@tanstack/angular-query-persist-client': patch ---- - -Simplify `provideTanStackQuery` to accept only a DI factory. Replace `provideTanStackQuery(TOKEN)` with `provideTanStackQuery(() => inject(TOKEN))`. - -Move `provideIsRestoring` to the internal entry point used by the persistence integration. Applications configure persistence with `withPersistQueryClient`; restoration state is managed by that integration. - -Simplify persistence callback return types without changing behavior: synchronous results and returned promises remain supported, and promises are still awaited. diff --git a/.changeset/angular-ssr-zone-timers.md b/.changeset/angular-ssr-zone-timers.md deleted file mode 100644 index e92bad11e16..00000000000 --- a/.changeset/angular-ssr-zone-timers.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tanstack/angular-query': patch ---- - -Prevent Zone.js server rendering from waiting for Query's background timers. Run adapter-owned Query operations outside Angular's zone while retaining PendingTasks tracking for fetches and mutations. Apply server retry and garbage-collection defaults per client without replacing global environment, notification, or timer configuration. diff --git a/.changeset/angular-stable-release.md b/.changeset/angular-stable-release.md index 0f74358991b..7577a4d58ad 100644 --- a/.changeset/angular-stable-release.md +++ b/.changeset/angular-stable-release.md @@ -4,6 +4,4 @@ '@tanstack/angular-query-persist-client': major --- -Introduce the Angular packages at `5.0.0-rc.0`. Add the stable Angular Query adapter for Angular 20.1+, with effect-managed subscriptions, factory-based providers, SSR hydration controls, Resource interoperability, and an Angular CLI schematic. Add standalone Angular devtools and connect the persistence integration to the stable adapter. - -The experimental adapter remains available during migration. Existing persistence integration users must switch their adapter imports to `@tanstack/angular-query` and pass factories to `provideTanStackQuery` and `withPersistQueryClient`. +Add the stable Angular Query adapter for Angular 20.1+. It includes SSR support, Resource API interoperability, persistence integration, improved internal subscription and pending tasks management, stable `injectQueries` and consistency improvements in the API. diff --git a/.changeset/angular-store-zone-boundary.md b/.changeset/angular-store-zone-boundary.md deleted file mode 100644 index c579cfeed5e..00000000000 --- a/.changeset/angular-store-zone-boundary.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tanstack/angular-query': patch ---- - -Centralize external-store reads, subscriptions, and cleanup outside Angular's zone. Preserve separate boundaries for reactive option updates and imperative operations so Query background timers do not delay server rendering. diff --git a/.changeset/persist-inject-factory.md b/.changeset/persist-inject-factory.md deleted file mode 100644 index 481a8f43d88..00000000000 --- a/.changeset/persist-inject-factory.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tanstack/angular-query-persist-client': minor ---- - -Run the Angular persist factory in an injection context and drop the `deps` option, matching `withDevtools`. diff --git a/.changeset/reactive-devtools-options.md b/.changeset/reactive-devtools-options.md deleted file mode 100644 index 8bd406ef26c..00000000000 --- a/.changeset/reactive-devtools-options.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@tanstack/angular-query-devtools': minor ---- - -Make mutable Angular devtools options individually signal-aware, construct the -devtools synchronously, and run reactive DOM updates in the after-render write -phase. diff --git a/integrations/angular-cli-20/.gitignore b/integrations/angular-cli/.gitignore similarity index 100% rename from integrations/angular-cli-20/.gitignore rename to integrations/angular-cli/.gitignore diff --git a/integrations/angular-cli-20/.vscode/extensions.json b/integrations/angular-cli/.vscode/extensions.json similarity index 100% rename from integrations/angular-cli-20/.vscode/extensions.json rename to integrations/angular-cli/.vscode/extensions.json diff --git a/integrations/angular-cli-20/.vscode/launch.json b/integrations/angular-cli/.vscode/launch.json similarity index 100% rename from integrations/angular-cli-20/.vscode/launch.json rename to integrations/angular-cli/.vscode/launch.json diff --git a/integrations/angular-cli-20/.vscode/tasks.json b/integrations/angular-cli/.vscode/tasks.json similarity index 100% rename from integrations/angular-cli-20/.vscode/tasks.json rename to integrations/angular-cli/.vscode/tasks.json diff --git a/integrations/angular-cli-20/README.md b/integrations/angular-cli/README.md similarity index 96% rename from integrations/angular-cli-20/README.md rename to integrations/angular-cli/README.md index e2977417aad..a09dcb7a448 100644 --- a/integrations/angular-cli-20/README.md +++ b/integrations/angular-cli/README.md @@ -1,6 +1,6 @@ -# AngularCli20 +# Angular CLI -This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.0.0-rc.2. +This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 22. ## Development server diff --git a/integrations/angular-cli-20/angular.json b/integrations/angular-cli/angular.json similarity index 94% rename from integrations/angular-cli-20/angular.json rename to integrations/angular-cli/angular.json index ec9adeb50f6..9efece00d0b 100644 --- a/integrations/angular-cli-20/angular.json +++ b/integrations/angular-cli/angular.json @@ -10,7 +10,7 @@ }, "newProjectRoot": "projects", "projects": { - "angular-cli-20": { + "angular-cli": { "projectType": "application", "schematics": { "@schematics/angular:component": { @@ -85,10 +85,10 @@ "builder": "@angular/build:dev-server", "configurations": { "production": { - "buildTarget": "angular-cli-20:build:production" + "buildTarget": "angular-cli:build:production" }, "development": { - "buildTarget": "angular-cli-20:build:development" + "buildTarget": "angular-cli:build:development" } }, "defaultConfiguration": "development" diff --git a/integrations/angular-cli-20/package.json b/integrations/angular-cli/package.json similarity index 96% rename from integrations/angular-cli-20/package.json rename to integrations/angular-cli/package.json index 0fd7f49b12d..671b9adc74f 100644 --- a/integrations/angular-cli-20/package.json +++ b/integrations/angular-cli/package.json @@ -1,5 +1,5 @@ { - "name": "angular-cli-20", + "name": "angular-cli", "private": true, "scripts": { "ng": "ng", diff --git a/integrations/angular-cli-20/public/favicon.ico b/integrations/angular-cli/public/favicon.ico similarity index 100% rename from integrations/angular-cli-20/public/favicon.ico rename to integrations/angular-cli/public/favicon.ico diff --git a/integrations/angular-cli-20/src/app/app.config.ts b/integrations/angular-cli/src/app/app.config.ts similarity index 100% rename from integrations/angular-cli-20/src/app/app.config.ts rename to integrations/angular-cli/src/app/app.config.ts diff --git a/integrations/angular-cli-20/src/app/app.ts b/integrations/angular-cli/src/app/app.ts similarity index 100% rename from integrations/angular-cli-20/src/app/app.ts rename to integrations/angular-cli/src/app/app.ts diff --git a/integrations/angular-cli-20/src/index.html b/integrations/angular-cli/src/index.html similarity index 90% rename from integrations/angular-cli-20/src/index.html rename to integrations/angular-cli/src/index.html index 94f551d17bd..0928db7c056 100644 --- a/integrations/angular-cli-20/src/index.html +++ b/integrations/angular-cli/src/index.html @@ -2,7 +2,7 @@ - AngularCli20 + Angular CLI diff --git a/integrations/angular-cli-20/src/main.ts b/integrations/angular-cli/src/main.ts similarity index 100% rename from integrations/angular-cli-20/src/main.ts rename to integrations/angular-cli/src/main.ts diff --git a/integrations/angular-cli-20/src/styles.css b/integrations/angular-cli/src/styles.css similarity index 100% rename from integrations/angular-cli-20/src/styles.css rename to integrations/angular-cli/src/styles.css diff --git a/integrations/angular-cli-20/tsconfig.app.json b/integrations/angular-cli/tsconfig.app.json similarity index 100% rename from integrations/angular-cli-20/tsconfig.app.json rename to integrations/angular-cli/tsconfig.app.json diff --git a/integrations/angular-cli-20/tsconfig.json b/integrations/angular-cli/tsconfig.json similarity index 100% rename from integrations/angular-cli-20/tsconfig.json rename to integrations/angular-cli/tsconfig.json diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0052ab846c2..ab72aecd741 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2405,7 +2405,7 @@ importers: specifier: ^6.4.1 version: 6.4.1(@types/node@22.19.15)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0) - integrations/angular-cli-20: + integrations/angular-cli: dependencies: '@angular/common': specifier: ^22.0.0 From dab38c09b0a9404708a5bfff3257586dbe1dfda7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Wed, 16 Sep 2026 19:45:45 -0300 Subject: [PATCH 3/9] docs(angular): clarify server retry behavior --- .../angular/guides/migrating-from-ngneat-query.md | 5 +---- docs/framework/angular/guides/ssr.md | 10 ++-------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/docs/framework/angular/guides/migrating-from-ngneat-query.md b/docs/framework/angular/guides/migrating-from-ngneat-query.md index e2d718671e6..491d0c2a1ec 100644 --- a/docs/framework/angular/guides/migrating-from-ngneat-query.md +++ b/docs/framework/angular/guides/migrating-from-ngneat-query.md @@ -5,8 +5,7 @@ title: Migrating from ngneat/query Angular Query requires Angular 20.1 or newer. -This guide uses `@ngneat/query` in its examples. The same migration applies to its -`@openng/query` fork. +This guide uses `@ngneat/query` in its examples. ## Replace the packages @@ -19,8 +18,6 @@ npm uninstall @ngneat/query @ngneat/query-devtools @tanstack/query-core npm install @tanstack/angular-query @tanstack/angular-query-devtools ``` -If you use OpenNG, uninstall `@openng/query` and `@openng/query-devtools` instead. - ## Configure the `QueryClient` Replace `provideQueryClientOptions` with a `QueryClient` factory passed to diff --git a/docs/framework/angular/guides/ssr.md b/docs/framework/angular/guides/ssr.md index a8a42e95294..2b6b727796f 100644 --- a/docs/framework/angular/guides/ssr.md +++ b/docs/framework/angular/guides/ssr.md @@ -11,12 +11,6 @@ builds on the same setup with browser persistence. ## Query client factory -`provideTanStackQuery` registers the factory with Angular's `useFactory`. It runs once per root injector and in an injection context, so it can call `inject()`. Browser- and server-specific query defaults can stay inside this factory. - -Angular Query runs its query work outside `NgZone`, so background cache timers do not delay server rendering. Pending queries and mutations still participate in Angular's stability tracking. Server clients default to no retries and `gcTime: Infinity`; explicit client defaults are preserved. - -If you call `QueryClient` directly during rendering with a finite `gcTime`, run that work outside `NgZone` too. Await it or use Angular's `PendingTasks` when the HTML needs its result. - ```ts import { isPlatformBrowser } from '@angular/common' import { inject, PLATFORM_ID } from '@angular/core' @@ -28,8 +22,8 @@ export function createQueryClient() { return new QueryClient({ defaultOptions: { queries: { - // Keep hydrated data fresh briefly to avoid an immediate browser refetch. - staleTime: isBrowser ? 60_000 : 0, + // Retry failed queries in the browser, but not on the server. + retry: isBrowser ? 3 : 0, }, }, }) From b63b735f49ba50f8787be3b92baf34f4b27dd0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Wed, 16 Sep 2026 20:10:17 -0300 Subject: [PATCH 4/9] chore: restore npm provenance configuration --- .npmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.npmrc b/.npmrc index a4be22c9207..268c392d3cb 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1 @@ -git-checks=false +provenance=true From 9bfd32ed04494887d3b56f7d7d5ac370e4879d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Thu, 17 Sep 2026 09:41:56 -0300 Subject: [PATCH 5/9] chore(angular): isolate prerelease versioning group --- .changeset/config.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.changeset/config.json b/.changeset/config.json index ff11f434eb5..f5cbfb9fc03 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -11,7 +11,10 @@ "fixed": [ [ "@tanstack/angular-query", - "@tanstack/angular-query-persist-client", + "@tanstack/angular-query-devtools", + "@tanstack/angular-query-persist-client" + ], + [ "@tanstack/eslint-plugin-query", "@tanstack/preact-query", "@tanstack/preact-query-devtools", From 9d2e03746f03809883ab4fa40d556c08d009dbbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Fri, 18 Sep 2026 11:20:16 -0300 Subject: [PATCH 6/9] fix(angular): explicit signal mapping in types Signals were mapped explicitly, but the types were not. This caused issues with generics where the type couldn't be inferred correctly. --- .../__tests__/inject-infinite-query.test-d.ts | 12 ++++++++++- .../src/__tests__/inject-mutation.test-d.ts | 12 ++++++++++- .../src/__tests__/inject-query.test-d.ts | 9 ++++++++- packages/angular-query/src/types.ts | 20 ++++++++++--------- .../angular-query/src/utils/result-fields.ts | 5 +++++ .../angular-query/src/utils/signal-proxy.ts | 6 ++++-- 6 files changed, 50 insertions(+), 14 deletions(-) diff --git a/packages/angular-query/src/__tests__/inject-infinite-query.test-d.ts b/packages/angular-query/src/__tests__/inject-infinite-query.test-d.ts index 4ea0a46baf3..e345c99ee67 100644 --- a/packages/angular-query/src/__tests__/inject-infinite-query.test-d.ts +++ b/packages/angular-query/src/__tests__/inject-infinite-query.test-d.ts @@ -1,10 +1,20 @@ import { describe, expectTypeOf, it } from 'vitest' import { injectInfiniteQuery, skipToken, toResource } from '..' -import type { CreateInfiniteQueryOptions } from '..' +import type { CreateInfiniteQueryOptions, CreateInfiniteQueryResult } from '..' import type { Signal } from '@angular/core' import type { InfiniteData } from '@tanstack/query-core' describe('injectInfiniteQuery', () => { + it('supports reading data from a generic result type', () => { + const readPages = >( + query: CreateInfiniteQueryResult, + ) => query.data()?.pages + + expectTypeOf(readPages).toBeCallableWith( + {} as CreateInfiniteQueryResult>, + ) + }) + it('should expose status predicates as Angular signals', () => { const query = injectInfiniteQuery(() => ({ queryKey: ['infiniteQuery'], diff --git a/packages/angular-query/src/__tests__/inject-mutation.test-d.ts b/packages/angular-query/src/__tests__/inject-mutation.test-d.ts index 489fa0302c1..43cf11f42f9 100644 --- a/packages/angular-query/src/__tests__/inject-mutation.test-d.ts +++ b/packages/angular-query/src/__tests__/inject-mutation.test-d.ts @@ -1,7 +1,7 @@ import { describe, expectTypeOf, it } from 'vitest' import { sleep } from '@tanstack/query-test-utils' import { injectMutation } from '..' -import type { CreateMutationOptions } from '..' +import type { CreateMutationOptions, CreateMutationResult } from '..' import type { Signal } from '@angular/core' import type { MutationFunctionContext, @@ -10,6 +10,16 @@ import type { } from '@tanstack/query-core' describe('injectMutation', () => { + it('supports reading data from a generic result type', () => { + const readId = ( + mutation: CreateMutationResult, + ) => mutation.data()?.id + + expectTypeOf(readId).toBeCallableWith( + {} as CreateMutationResult<{ id: number }>, + ) + }) + describe('Discriminated union return type', () => { it('data should be possibly undefined by default', () => { const mutation = injectMutation(() => ({ diff --git a/packages/angular-query/src/__tests__/inject-query.test-d.ts b/packages/angular-query/src/__tests__/inject-query.test-d.ts index ecc517df018..f872892eeb2 100644 --- a/packages/angular-query/src/__tests__/inject-query.test-d.ts +++ b/packages/angular-query/src/__tests__/inject-query.test-d.ts @@ -1,7 +1,7 @@ import { describe, expectTypeOf, it } from 'vitest' import { sleep } from '@tanstack/query-test-utils' import { injectQuery, queryOptions, toResource } from '..' -import type { CreateQueryOptions } from '..' +import type { CreateQueryOptions, CreateQueryResult } from '..' import type { Resource, Signal } from '@angular/core' describe('initialData', () => { @@ -162,6 +162,13 @@ describe('initialData', () => { }) }) +it('supports reading data from a generic result type', () => { + const readId = (query: CreateQueryResult) => + query.data()?.id + + expectTypeOf(readId).toBeCallableWith({} as CreateQueryResult<{ id: number }>) +}) + describe('Discriminated union return type', () => { it('should expose status predicates as Angular signals', () => { const query = injectQuery(() => ({ diff --git a/packages/angular-query/src/types.ts b/packages/angular-query/src/types.ts index 2bdde723202..a157d08061c 100644 --- a/packages/angular-query/src/types.ts +++ b/packages/angular-query/src/types.ts @@ -16,7 +16,12 @@ import type { QueryObserverResult, } from '@tanstack/query-core' import type { Signal } from '@angular/core' -import type { MapToSignals, MethodKeys } from './utils/signal-proxy' +import type { MapToSignals } from './utils/signal-proxy' +import type { + InfiniteQueryResultFields, + MutationResultFields, + QueryResultFields, +} from './utils/result-fields' type SignalFunction any> = T & Signal> @@ -209,7 +214,7 @@ export type CreateBaseQueryResult< > = BaseQueryNarrowing & MapToSignals< OmitKeyof, - MethodKeys> + QueryResultFields > /** @@ -239,7 +244,7 @@ export type DefinedCreateQueryResult< > = DefinedQueryNarrowing & MapToSignals< OmitKeyof, - MethodKeys> + QueryResultFields > /** @@ -257,7 +262,7 @@ export type CreateInfiniteQueryResult< TState extends InfiniteQueryObserverResult = InfiniteQueryObserverResult, > = BaseInfiniteQueryNarrowing & - MapToSignals> + MapToSignals /** * The result of `injectInfiniteQuery` when `initialData` is set — `data` is never `undefined`. Same shape as @@ -275,10 +280,7 @@ export type DefinedCreateInfiniteQueryResult< TError > = DefinedInfiniteQueryObserverResult, > = DefinedInfiniteQueryNarrowing & - MapToSignals< - TDefinedInfiniteQueryObserver, - MethodKeys - > + MapToSignals /** * The options accepted by `injectMutation`. Same as {@link MutationObserverOptions} from @@ -484,5 +486,5 @@ export type CreateMutationResult< > = BaseMutationNarrowing & MapToSignals< OmitKeyof, - MethodKeys> + MutationResultFields > diff --git a/packages/angular-query/src/utils/result-fields.ts b/packages/angular-query/src/utils/result-fields.ts index 598ac07b4e7..bf2b8239950 100644 --- a/packages/angular-query/src/utils/result-fields.ts +++ b/packages/angular-query/src/utils/result-fields.ts @@ -64,10 +64,15 @@ const mutationFields = { export const queryResultFields = /* @__PURE__ */ Object.keys( queryFields, ) as Array +export type QueryResultFields = (typeof queryResultFields)[number] + export const infiniteQueryResultFields = /* @__PURE__ */ Object.keys( infiniteQueryFields, ) as Array +export type InfiniteQueryResultFields = + (typeof infiniteQueryResultFields)[number] export const mutationResultFields = /* @__PURE__ */ Object.keys( mutationFields, ) as Array +export type MutationResultFields = (typeof mutationResultFields)[number] diff --git a/packages/angular-query/src/utils/signal-proxy.ts b/packages/angular-query/src/utils/signal-proxy.ts index cc6305bc42d..53621622eb8 100644 --- a/packages/angular-query/src/utils/signal-proxy.ts +++ b/packages/angular-query/src/utils/signal-proxy.ts @@ -5,8 +5,10 @@ export type MethodKeys = { [K in keyof T]: T[K] extends (...args: Array) => any ? K : never }[keyof T] -export type MapToSignals = never> = { - [K in keyof T]: K extends TExcludeFields ? T[K] : Signal +export type MapToSignals = { + [K in keyof T as K extends TSignalFields ? K : never]: Signal +} & { + [K in keyof T as K extends TSignalFields ? never : K]: T[K] } /** From 289b4a6c24826016fa7124a09e296c00a98c38ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Sun, 20 Sep 2026 19:33:50 -0300 Subject: [PATCH 7/9] fix(angular): correctly peer angular >=20.1 --- packages/angular-query-devtools/package.json | 4 ++-- packages/angular-query-persist-client/package.json | 4 ++-- packages/angular-query/package.json | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/angular-query-devtools/package.json b/packages/angular-query-devtools/package.json index 7055d656b93..719f8557e57 100644 --- a/packages/angular-query-devtools/package.json +++ b/packages/angular-query-devtools/package.json @@ -102,8 +102,8 @@ "zone.js": "^0.16.0" }, "peerDependencies": { - "@angular/common": ">=22.0.0", - "@angular/core": ">=22.0.0", + "@angular/common": ">=20.1.0", + "@angular/core": ">=20.1.0", "@tanstack/angular-query": "workspace:^" }, "publishConfig": { diff --git a/packages/angular-query-persist-client/package.json b/packages/angular-query-persist-client/package.json index 4acb5fa11fc..e951c46f960 100644 --- a/packages/angular-query-persist-client/package.json +++ b/packages/angular-query-persist-client/package.json @@ -69,8 +69,8 @@ "zone.js": "^0.16.0" }, "peerDependencies": { - "@angular/common": ">=22.0.0", - "@angular/core": ">=22.0.0", + "@angular/common": ">=20.1.0", + "@angular/core": ">=20.1.0", "@tanstack/angular-query": "workspace:^" } } diff --git a/packages/angular-query/package.json b/packages/angular-query/package.json index 447dc7513d3..22e2aed2fa0 100644 --- a/packages/angular-query/package.json +++ b/packages/angular-query/package.json @@ -99,8 +99,8 @@ "zone.js": "^0.16.0" }, "peerDependencies": { - "@angular/common": ">=22.0.0", - "@angular/core": ">=22.0.0" + "@angular/common": ">=20.1.0", + "@angular/core": ">=20.1.0" }, "publishConfig": { "directory": "dist", From 6d89722868616bd3764a12633f4043e2954c9f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Sun, 20 Sep 2026 20:04:29 -0300 Subject: [PATCH 8/9] docs(angular): regenerate docs --- .../reference/classes/CancelledError.md | 8 +- .../classes/InfiniteQueryObserver.md | 66 +++--- .../angular/reference/classes/Mutation.md | 32 ++- .../reference/classes/MutationCache.md | 44 ++-- .../reference/classes/MutationObserver.md | 36 ++-- .../reference/classes/QueriesObserver.md | 32 ++- .../angular/reference/classes/Query.md | 60 +++--- .../angular/reference/classes/QueryCache.md | 50 ++--- .../angular/reference/classes/QueryClient.md | 84 ++++---- .../reference/classes/QueryObserver.md | 66 +++--- .../defaultShouldDehydrateMutation.md | 2 +- .../functions/defaultShouldDehydrateQuery.md | 2 +- .../angular/reference/functions/dehydrate.md | 8 +- .../reference/functions/dehydrateQuery.md | 2 +- .../functions/experimental_streamedQuery.md | 44 +--- .../angular/reference/functions/hashKey.md | 2 +- .../angular/reference/functions/hydrate.md | 2 +- .../functions/infiniteQueryOptions.md | 18 +- .../functions/injectInfiniteQuery.md | 96 +++++++-- .../reference/functions/injectIsFetching.md | 41 +--- .../reference/functions/injectIsMutating.md | 27 +-- .../reference/functions/injectIsRestoring.md | 8 +- .../reference/functions/injectMutation.md | 143 ++----------- .../functions/injectMutationState.md | 60 +----- .../reference/functions/injectQueries.md | 49 +++-- .../reference/functions/injectQuery.md | 188 ++++++++++++----- .../reference/functions/isCancelledError.md | 2 +- .../reference/functions/keepPreviousData.md | 2 +- .../reference/functions/matchMutation.md | 2 +- .../angular/reference/functions/matchQuery.md | 2 +- .../reference/functions/mutationOptions.md | 8 +- .../angular/reference/functions/noop.md | 4 +- .../reference/functions/partialMatchKey.md | 2 +- .../functions/provideTanStackQuery.md | 56 +++-- .../reference/functions/queryOptions.md | 198 +++++++++++++++--- .../reference/functions/replaceEqualDeep.md | 2 +- .../reference/functions/shouldThrowError.md | 2 +- .../angular/reference/functions/toResource.md | 2 +- .../reference/functions/withHydrationKey.md | 4 +- .../functions/withNoQueryHydration.md | 2 +- docs/framework/angular/reference/index.md | 127 +++++++++++ .../interfaces/BaseInfiniteQueryNarrowing.md | 36 +--- .../interfaces/BaseMutationNarrowing.md | 54 +---- .../interfaces/BaseQueryNarrowing.md | 38 +--- .../reference/interfaces/CancelOptions.md | 5 +- .../interfaces/CreateInfiniteQueryOptions.md | 76 +++---- .../interfaces/CreateMutationOptions.md | 36 ++-- .../reference/interfaces/DefaultOptions.md | 4 +- .../DefinedInfiniteQueryNarrowing.md | 36 +--- .../interfaces/DefinedQueryNarrowing.md | 36 +--- .../reference/interfaces/DehydrateOptions.md | 2 +- .../reference/interfaces/DehydratedState.md | 2 +- .../interfaces/EnsureQueryDataOptions.md | 40 ++-- .../interfaces/FetchNextPageOptions.md | 10 +- .../interfaces/FetchPreviousPageOptions.md | 10 +- .../reference/interfaces/FetchQueryOptions.md | 38 ++-- .../reference/interfaces/FocusManager.md | 24 +-- .../reference/interfaces/HydrateOptions.md | 2 +- .../reference/interfaces/InfiniteData.md | 5 +- .../InfiniteQueryObserverBaseResult.md | 6 +- ...InfiniteQueryObserverLoadingErrorResult.md | 4 +- .../InfiniteQueryObserverLoadingResult.md | 4 +- .../InfiniteQueryObserverOptions.md | 66 +++--- .../InfiniteQueryObserverPendingResult.md | 4 +- .../InfiniteQueryObserverPlaceholderResult.md | 4 +- ...InfiniteQueryObserverRefetchErrorResult.md | 4 +- .../InfiniteQueryObserverSuccessResult.md | 4 +- .../InfiniteQueryPageParamsOptions.md | 8 +- .../reference/interfaces/InitialPageParam.md | 8 +- .../interfaces/InjectQueriesOptions.md | 33 +-- .../reference/interfaces/InvalidateOptions.md | 10 +- .../interfaces/InvalidateQueryFilters.md | 20 +- .../reference/interfaces/MutateOptions.md | 2 +- .../interfaces/MutationCacheConfig.md | 2 +- .../reference/interfaces/MutationFilters.md | 4 +- .../interfaces/MutationObserverBaseResult.md | 4 +- .../interfaces/MutationObserverErrorResult.md | 2 +- .../interfaces/MutationObserverIdleResult.md | 2 +- .../MutationObserverLoadingResult.md | 2 +- .../interfaces/MutationObserverOptions.md | 32 +-- .../MutationObserverSuccessResult.md | 2 +- .../reference/interfaces/MutationOptions.md | 30 +-- .../reference/interfaces/MutationState.md | 4 +- .../reference/interfaces/NotifyEvent.md | 4 +- .../reference/interfaces/OnlineManager.md | 22 +- .../interfaces/QueriesObserverOptions.md | 2 +- .../reference/interfaces/QueryCacheConfig.md | 2 +- .../reference/interfaces/QueryClientConfig.md | 2 +- .../interfaces/QueryExecuteOptions.md | 40 ++-- .../reference/interfaces/QueryFeature.md | 14 +- .../reference/interfaces/QueryFilters.md | 18 +- .../interfaces/QueryObserverBaseResult.md | 6 +- .../QueryObserverLoadingErrorResult.md | 4 +- .../interfaces/QueryObserverLoadingResult.md | 4 +- .../interfaces/QueryObserverOptions.md | 60 +++--- .../interfaces/QueryObserverPendingResult.md | 4 +- .../QueryObserverPlaceholderResult.md | 4 +- .../QueryObserverRefetchErrorResult.md | 4 +- .../interfaces/QueryObserverSuccessResult.md | 4 +- .../reference/interfaces/QueryOptions.md | 34 +-- .../reference/interfaces/QueryResource.md | 117 +---------- .../reference/interfaces/QueryState.md | 6 +- .../reference/interfaces/RefetchOptions.md | 10 +- .../interfaces/RefetchQueryFilters.md | 18 +- .../angular/reference/interfaces/Register.md | 22 +- .../reference/interfaces/ResetOptions.md | 10 +- .../reference/interfaces/ResultOptions.md | 8 +- .../reference/interfaces/SetDataOptions.md | 6 +- .../reference/interfaces/TimeoutManager.md | 12 +- .../reference/type-aliases/AnyDataTag.md | 2 +- .../type-aliases/CreateBaseMutationResult.md | 6 +- .../type-aliases/CreateBaseQueryResult.md | 13 +- .../type-aliases/CreateInfiniteQueryResult.md | 15 +- .../type-aliases/CreateMutateAsyncFunction.md | 5 +- .../type-aliases/CreateMutateFunction.md | 6 +- .../type-aliases/CreateMutationResult.md | 9 +- .../type-aliases/CreateQueryOptions.md | 6 +- .../type-aliases/CreateQueryResult.md | 4 +- .../angular/reference/type-aliases/DataTag.md | 2 +- .../reference/type-aliases/DefaultError.md | 5 +- .../DefaultedInfiniteQueryObserverOptions.md | 2 +- .../DefaultedQueryObserverOptions.md | 2 +- .../DefinedCreateInfiniteQueryResult.md | 10 +- .../type-aliases/DefinedCreateQueryResult.md | 10 +- .../DefinedInfiniteQueryObserverResult.md | 2 +- .../DefinedInitialDataInfiniteOptions.md | 5 +- .../type-aliases/DefinedInitialDataOptions.md | 5 +- .../DefinedQueryObserverResult.md | 2 +- .../type-aliases/DistributiveOmit.md | 2 +- .../EnsureInfiniteQueryDataOptions.md | 2 +- .../type-aliases/FetchInfiniteQueryOptions.md | 2 +- .../reference/type-aliases/FetchStatus.md | 2 +- .../type-aliases/GetNextPageParamFunction.md | 2 +- .../GetPreviousPageParamFunction.md | 2 +- .../type-aliases/InferDataFromTag.md | 2 +- .../type-aliases/InferErrorFromTag.md | 2 +- .../InfiniteQueryExecuteOptions.md | 2 +- .../InfiniteQueryObserverResult.md | 2 +- .../type-aliases/InitialDataFunction.md | 2 +- .../reference/type-aliases/ManagedTimerId.md | 2 +- .../reference/type-aliases/MutateFunction.md | 2 +- .../type-aliases/MutateFunctionRest.md | 2 +- .../type-aliases/MutationCacheNotifyEvent.md | 2 +- .../type-aliases/MutationFunction.md | 2 +- .../type-aliases/MutationFunctionContext.md | 2 +- .../reference/type-aliases/MutationKey.md | 5 +- .../reference/type-aliases/MutationMeta.md | 5 +- .../type-aliases/MutationObserverResult.md | 2 +- .../reference/type-aliases/MutationScope.md | 6 +- .../type-aliases/MutationStateOptions.md | 35 +--- .../reference/type-aliases/MutationStatus.md | 2 +- .../reference/type-aliases/NetworkMode.md | 2 +- .../type-aliases/NonUndefinedGuard.md | 2 +- .../reference/type-aliases/NotifyEventType.md | 2 +- .../type-aliases/NotifyOnChangeProps.md | 2 +- .../reference/type-aliases/OmitKeyof.md | 2 +- .../reference/type-aliases/Override.md | 2 +- .../type-aliases/PlaceholderDataFunction.md | 2 +- .../reference/type-aliases/QueriesOptions.md | 8 - .../QueriesPlaceholderDataFunction.md | 2 +- .../reference/type-aliases/QueriesResults.md | 8 - .../type-aliases/QueryBooleanOption.md | 2 +- .../type-aliases/QueryCacheNotifyEvent.md | 2 +- .../reference/type-aliases/QueryFunction.md | 2 +- .../type-aliases/QueryFunctionContext.md | 2 +- .../reference/type-aliases/QueryKey.md | 5 +- .../type-aliases/QueryKeyHashFunction.md | 2 +- .../type-aliases/QueryKeyWithDataTag.md | 2 +- .../reference/type-aliases/QueryMeta.md | 5 +- .../type-aliases/QueryObserverResult.md | 2 +- .../reference/type-aliases/QueryPersister.md | 2 +- .../reference/type-aliases/QueryStatus.md | 2 +- .../reference/type-aliases/SkipToken.md | 2 +- .../reference/type-aliases/StaleTime.md | 2 +- .../type-aliases/StaleTimeFunction.md | 6 +- .../reference/type-aliases/ThrowOnError.md | 2 +- .../reference/type-aliases/TimeoutCallback.md | 2 +- .../reference/type-aliases/TimeoutProvider.md | 2 +- .../UndefinedInitialDataInfiniteOptions.md | 5 +- .../UndefinedInitialDataOptions.md | 5 +- .../reference/type-aliases/UnsetMarker.md | 2 +- .../UnusedSkipTokenInfiniteOptions.md | 6 +- .../type-aliases/UnusedSkipTokenOptions.md | 5 +- .../angular/reference/type-aliases/Updater.md | 2 +- .../reference/type-aliases/WithRequired.md | 2 +- .../type-aliases/dataTagErrorSymbol.md | 2 +- .../reference/type-aliases/dataTagSymbol.md | 2 +- .../reference/variables/dataTagErrorSymbol.md | 4 +- .../reference/variables/dataTagSymbol.md | 4 +- .../reference/variables/defaultScheduler.md | 4 +- .../reference/variables/environmentManager.md | 4 +- .../reference/variables/focusManager.md | 2 +- .../angular/reference/variables/isServer.md | 2 +- .../reference/variables/notifyManager.md | 4 +- .../reference/variables/onlineManager.md | 2 +- .../angular/reference/variables/skipToken.md | 4 +- .../reference/variables/timeoutManager.md | 2 +- .../reference/variables/unsetMarker.md | 4 +- 198 files changed, 1454 insertions(+), 1626 deletions(-) diff --git a/docs/framework/angular/reference/classes/CancelledError.md b/docs/framework/angular/reference/classes/CancelledError.md index 5bd8c049574..4010dfce61c 100644 --- a/docs/framework/angular/reference/classes/CancelledError.md +++ b/docs/framework/angular/reference/classes/CancelledError.md @@ -3,7 +3,7 @@ id: CancelledError title: CancelledError --- -Defined in: [packages/query-core/src/retryer.ts:81](https://github.com/TanStack/query/blob/main/packages/query-core/src/retryer.ts#L81) +Defined in: packages/query-core/dist-ts/src/retryer.d.ts:47 The error thrown by a `Retryer` (and surfaced to `query.promise`/`mutation`) when a fetch is cancelled, e.g. via `query.cancel()`. `revert`, if `true`, tells the caller to restore the state the query was in before the fetch @@ -36,7 +36,7 @@ try { new CancelledError(options?: CancelOptions): CancelledError; ``` -Defined in: [packages/query-core/src/retryer.ts:84](https://github.com/TanStack/query/blob/main/packages/query-core/src/retryer.ts#L84) +Defined in: packages/query-core/dist-ts/src/retryer.d.ts:50 #### Parameters @@ -110,7 +110,7 @@ Error.name optional revert: boolean; ``` -Defined in: [packages/query-core/src/retryer.ts:82](https://github.com/TanStack/query/blob/main/packages/query-core/src/retryer.ts#L82) +Defined in: packages/query-core/dist-ts/src/retryer.d.ts:48 *** @@ -120,7 +120,7 @@ Defined in: [packages/query-core/src/retryer.ts:82](https://github.com/TanStack/ optional silent: boolean; ``` -Defined in: [packages/query-core/src/retryer.ts:83](https://github.com/TanStack/query/blob/main/packages/query-core/src/retryer.ts#L83) +Defined in: packages/query-core/dist-ts/src/retryer.d.ts:49 *** diff --git a/docs/framework/angular/reference/classes/InfiniteQueryObserver.md b/docs/framework/angular/reference/classes/InfiniteQueryObserver.md index 5453760e839..5c90f3f9d73 100644 --- a/docs/framework/angular/reference/classes/InfiniteQueryObserver.md +++ b/docs/framework/angular/reference/classes/InfiniteQueryObserver.md @@ -3,7 +3,7 @@ id: InfiniteQueryObserver title: InfiniteQueryObserver --- -Defined in: [packages/query-core/src/infiniteQueryObserver.ts:41](https://github.com/TanStack/query/blob/main/packages/query-core/src/infiniteQueryObserver.ts#L41) +Defined in: packages/query-core/dist-ts/src/infiniteQueryObserver.d.ts:26 An `InfiniteQueryObserver` extends `QueryObserver` to observe and switch between infinite queries. It augments the base `QueryObserverResult` with @@ -58,7 +58,7 @@ const unsubscribe = observer.subscribe((result) => console.log(result)) new InfiniteQueryObserver(client: QueryClient, options: InfiniteQueryObserverOptions): InfiniteQueryObserver; ``` -Defined in: [packages/query-core/src/infiniteQueryObserver.ts:83](https://github.com/TanStack/query/blob/main/packages/query-core/src/infiniteQueryObserver.ts#L83) +Defined in: packages/query-core/dist-ts/src/infiniteQueryObserver.d.ts:30 #### Parameters @@ -86,7 +86,7 @@ Defined in: [packages/query-core/src/infiniteQueryObserver.ts:83](https://github protected fetch: ReplaceReturnType<(fetchOptions: ObserverFetchOptions) => Promise>, Promise>>; ``` -Defined in: [packages/query-core/src/infiniteQueryObserver.ts:72](https://github.com/TanStack/query/blob/main/packages/query-core/src/infiniteQueryObserver.ts#L72) +Defined in: packages/query-core/dist-ts/src/infiniteQueryObserver.d.ts:29 #### Overrides @@ -102,7 +102,7 @@ QueryObserver.fetch getCurrentResult: ReplaceReturnType<() => QueryObserverResult, InfiniteQueryObserverResult>; ``` -Defined in: [packages/query-core/src/infiniteQueryObserver.ts:60](https://github.com/TanStack/query/blob/main/packages/query-core/src/infiniteQueryObserver.ts#L60) +Defined in: packages/query-core/dist-ts/src/infiniteQueryObserver.d.ts:28 Returns the most recently computed `QueryObserverResult` for the observed query. This is a point-in-time read; to be notified of updates @@ -130,7 +130,7 @@ QueryObserver.getCurrentResult protected listeners: Set>; ``` -Defined in: [packages/query-core/src/subscribable.ts:7](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L7) +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:2 #### Inherited from @@ -144,7 +144,7 @@ Defined in: [packages/query-core/src/subscribable.ts:7](https://github.com/TanSt options: QueryObserverOptions, TQueryKey>; ``` -Defined in: [packages/query-core/src/queryObserver.ts:89](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L89) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:31 #### Inherited from @@ -158,7 +158,7 @@ Defined in: [packages/query-core/src/queryObserver.ts:89](https://github.com/Tan subscribe: (listener: InfiniteQueryObserverListener) => () => void; ``` -Defined in: [packages/query-core/src/infiniteQueryObserver.ts:55](https://github.com/TanStack/query/blob/main/packages/query-core/src/infiniteQueryObserver.ts#L55) +Defined in: packages/query-core/dist-ts/src/infiniteQueryObserver.d.ts:27 Registers a listener to be called on every update this object notifies about. Returns a function that removes the listener again — call it to stop listening. The base class never drops a listener @@ -206,7 +206,7 @@ QueryObserver.subscribe protected bindMethods(): void; ``` -Defined in: [packages/query-core/src/infiniteQueryObserver.ts:96](https://github.com/TanStack/query/blob/main/packages/query-core/src/infiniteQueryObserver.ts#L96) +Defined in: packages/query-core/dist-ts/src/infiniteQueryObserver.d.ts:31 #### Returns @@ -224,7 +224,7 @@ Defined in: [packages/query-core/src/infiniteQueryObserver.ts:96](https://github protected createResult(query: Query, TQueryKey>, options: InfiniteQueryObserverOptions): InfiniteQueryObserverResult; ``` -Defined in: [packages/query-core/src/infiniteQueryObserver.ts:201](https://github.com/TanStack/query/blob/main/packages/query-core/src/infiniteQueryObserver.ts#L201) +Defined in: packages/query-core/dist-ts/src/infiniteQueryObserver.d.ts:84 #### Parameters @@ -252,7 +252,7 @@ Defined in: [packages/query-core/src/infiniteQueryObserver.ts:201](https://githu destroy(): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:161](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L161) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:53 Stops observing the current query: clears all listeners, cancels the stale and refetch-interval timers, and removes this observer from the @@ -274,7 +274,7 @@ query it was observing. fetchNextPage(options?: FetchNextPageOptions): Promise>; ``` -Defined in: [packages/query-core/src/infiniteQueryObserver.ts:161](https://github.com/TanStack/query/blob/main/packages/query-core/src/infiniteQueryObserver.ts#L161) +Defined in: packages/query-core/dist-ts/src/infiniteQueryObserver.d.ts:64 Fetches the next page of the infinite query and returns a promise that resolves with the resulting `InfiniteQueryObserverResult`. The page @@ -314,7 +314,7 @@ if (hasNextPage) { fetchOptimistic(options: QueryObserverOptions, TQueryKey>): Promise>; ``` -Defined in: [packages/query-core/src/queryObserver.ts:395](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L395) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:134 Fetches a query defined by the given options without affecting this observer's own tracked query or result, and returns a promise that @@ -354,7 +354,7 @@ console.log(result.data) fetchPreviousPage(options?: FetchPreviousPageOptions): Promise>; ``` -Defined in: [packages/query-core/src/infiniteQueryObserver.ts:190](https://github.com/TanStack/query/blob/main/packages/query-core/src/infiniteQueryObserver.ts#L190) +Defined in: packages/query-core/dist-ts/src/infiniteQueryObserver.d.ts:83 Fetches the previous page of the infinite query and returns a promise that resolves with the resulting `InfiniteQueryObserverResult`. The page @@ -394,7 +394,7 @@ if (hasPreviousPage) { getCurrentQuery(): Query, TQueryKey>; ``` -Defined in: [packages/query-core/src/queryObserver.ts:357](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L357) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:106 Returns the `Query` instance this observer is currently observing. @@ -414,7 +414,7 @@ Returns the `Query` instance this observer is currently observing. getOptimisticResult(options: DefaultedInfiniteQueryObserverOptions): InfiniteQueryObserverResult; ``` -Defined in: [packages/query-core/src/infiniteQueryObserver.ts:127](https://github.com/TanStack/query/blob/main/packages/query-core/src/infiniteQueryObserver.ts#L127) +Defined in: packages/query-core/dist-ts/src/infiniteQueryObserver.d.ts:45 The infinite-query counterpart of [QueryObserver#getOptimisticResult](QueryObserver.md#getoptimisticresult), marking the options as an infinite query before delegating to it. Called by framework adapters (e.g. @@ -443,9 +443,7 @@ synchronously. hasListeners(): boolean; ``` -Defined in: [packages/query-core/src/subscribable.ts:41](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L41) - -Returns `true` while at least one listener is registered, `false` once they have all unsubscribed. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:5 #### Returns @@ -463,7 +461,7 @@ Returns `true` while at least one listener is registered, `false` once they have protected onSubscribe(): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:110](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L110) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:34 #### Returns @@ -481,7 +479,7 @@ Defined in: [packages/query-core/src/queryObserver.ts:110](https://github.com/Ta protected onUnsubscribe(): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:124](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L124) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:35 #### Returns @@ -496,19 +494,19 @@ Defined in: [packages/query-core/src/queryObserver.ts:124](https://github.com/Ta ### refetch() ```ts -refetch(__namedParameters: RefetchOptions): Promise>; +refetch(__namedParameters?: RefetchOptions): Promise>; ``` -Defined in: [packages/query-core/src/queryObserver.ts:371](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L371) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:117 Refetches the observed query and returns a promise that resolves with the resulting `QueryObserverResult`. #### Parameters -##### \_\_namedParameters +##### \_\_namedParameters? -[`RefetchOptions`](../interfaces/RefetchOptions.md) = `{}` +[`RefetchOptions`](../interfaces/RefetchOptions.md) #### Returns @@ -533,7 +531,7 @@ console.log(result.data) setOptions(options: InfiniteQueryObserverOptions): void; ``` -Defined in: [packages/query-core/src/infiniteQueryObserver.ts:108](https://github.com/TanStack/query/blob/main/packages/query-core/src/infiniteQueryObserver.ts#L108) +Defined in: packages/query-core/dist-ts/src/infiniteQueryObserver.d.ts:38 Updates the observer's options. Behaves the same as `QueryObserver.setOptions`, additionally marking the options as @@ -562,7 +560,7 @@ implementation. shouldFetchOnReconnect(): boolean; ``` -Defined in: [packages/query-core/src/queryObserver.ts:135](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L135) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:41 Returns whether the observed query is currently stale and configured (via the `refetchOnReconnect` option) to refetch when the network @@ -584,7 +582,7 @@ reconnects. shouldFetchOnWindowFocus(): boolean; ``` -Defined in: [packages/query-core/src/queryObserver.ts:148](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L148) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:47 Returns whether the observed query is currently stale and configured (via the `refetchOnWindowFocus` option) to refetch when the window @@ -604,8 +602,8 @@ regains focus. ```ts trackProp(key: - | "error" | "data" + | "error" | "isError" | "isPending" | "isLoading" @@ -631,7 +629,7 @@ trackProp(key: | "fetchStatus"): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:350](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L350) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:102 Records that the given `QueryObserverResult` property was read, so a subsequent update only notifies this observer if a tracked property actually changed. Normally called indirectly via @@ -642,7 +640,7 @@ access themselves (e.g. through their own reactivity system) instead of via the ##### key -`"error"` | `"data"` | `"isError"` | `"isPending"` | `"isLoading"` | `"isLoadingError"` | `"isRefetchError"` | `"isSuccess"` | `"isPlaceholderData"` | `"status"` | `"dataUpdatedAt"` | `"errorUpdatedAt"` | `"failureCount"` | `"failureReason"` | `"errorUpdateCount"` | `"isFetched"` | `"isFetchedAfterMount"` | `"isFetching"` | `"isInitialLoading"` | `"isPaused"` | `"isRefetching"` | `"isStale"` | `"isEnabled"` | `"refetch"` | `"fetchStatus"` +`"data"` | `"error"` | `"isError"` | `"isPending"` | `"isLoading"` | `"isLoadingError"` | `"isRefetchError"` | `"isSuccess"` | `"isPlaceholderData"` | `"status"` | `"dataUpdatedAt"` | `"errorUpdatedAt"` | `"failureCount"` | `"failureReason"` | `"errorUpdateCount"` | `"isFetched"` | `"isFetchedAfterMount"` | `"isFetching"` | `"isInitialLoading"` | `"isPaused"` | `"isRefetching"` | `"isStale"` | `"isEnabled"` | `"refetch"` | `"fetchStatus"` #### Returns @@ -658,8 +656,8 @@ access themselves (e.g. through their own reactivity system) instead of via the ```ts trackResult(result: QueryObserverResult, onPropTracked?: (key: - | "error" | "data" + | "error" | "isError" | "isPending" | "isLoading" @@ -685,7 +683,7 @@ trackResult(result: QueryObserverResult, onPropTracked?: (key: | "fetchStatus") => void): QueryObserverResult; ``` -Defined in: [packages/query-core/src/queryObserver.ts:331](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L331) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:95 Wraps a `QueryObserverResult` in a `Proxy` that records which properties are read, via [QueryObserver#trackProp](QueryObserver.md#trackprop) (and an optional `onPropTracked` callback). Used by framework @@ -701,8 +699,8 @@ properties you actually read" behavior. ##### onPropTracked? (`key`: - \| `"error"` \| `"data"` + \| `"error"` \| `"isError"` \| `"isPending"` \| `"isLoading"` @@ -743,7 +741,7 @@ properties you actually read" behavior. updateResult(): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:735](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L735) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:142 Recomputes and stores the current result from the current query/options, notifying listeners if it changed. Framework adapters call this right after subscribing to make sure no query diff --git a/docs/framework/angular/reference/classes/Mutation.md b/docs/framework/angular/reference/classes/Mutation.md index 49975b76a75..19209829381 100644 --- a/docs/framework/angular/reference/classes/Mutation.md +++ b/docs/framework/angular/reference/classes/Mutation.md @@ -3,7 +3,7 @@ id: Mutation title: Mutation --- -Defined in: [packages/query-core/src/mutation.ts:135](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutation.ts#L135) +Defined in: packages/query-core/dist-ts/src/mutation.d.ts:101 Represents a single mutation attempt. A `Mutation` holds the mutation's options, state (data/error/status), and the `MutationObserver`s currently @@ -52,7 +52,7 @@ const mutation = mutationCache.find({ mutationKey: ['addPost'] }) new Mutation(config: MutationConfig): Mutation; ``` -Defined in: [packages/query-core/src/mutation.ts:152](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutation.ts#L152) +Defined in: packages/query-core/dist-ts/src/mutation.d.ts:106 #### Parameters @@ -78,7 +78,7 @@ Removable.constructor gcTime: number; ``` -Defined in: [packages/query-core/src/removable.ts:11](https://github.com/TanStack/query/blob/main/packages/query-core/src/removable.ts#L11) +Defined in: packages/query-core/dist-ts/src/removable.d.ts:3 #### Inherited from @@ -94,7 +94,7 @@ Removable.gcTime readonly mutationId: number; ``` -Defined in: [packages/query-core/src/mutation.ts:143](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutation.ts#L143) +Defined in: packages/query-core/dist-ts/src/mutation.d.ts:105 *** @@ -104,7 +104,7 @@ Defined in: [packages/query-core/src/mutation.ts:143](https://github.com/TanStac options: MutationOptions; ``` -Defined in: [packages/query-core/src/mutation.ts:142](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutation.ts#L142) +Defined in: packages/query-core/dist-ts/src/mutation.d.ts:104 *** @@ -114,7 +114,7 @@ Defined in: [packages/query-core/src/mutation.ts:142](https://github.com/TanStac state: MutationState; ``` -Defined in: [packages/query-core/src/mutation.ts:141](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutation.ts#L141) +Defined in: packages/query-core/dist-ts/src/mutation.d.ts:103 ## Accessors @@ -126,7 +126,7 @@ Defined in: [packages/query-core/src/mutation.ts:141](https://github.com/TanStac get meta(): Record | undefined; ``` -Defined in: [packages/query-core/src/mutation.ts:179](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutation.ts#L179) +Defined in: packages/query-core/dist-ts/src/mutation.d.ts:112 The `meta` object passed in the mutation's options, if any. @@ -142,7 +142,7 @@ The `meta` object passed in the mutation's options, if any. protected clearGcTimeout(): void; ``` -Defined in: [packages/query-core/src/removable.ts:41](https://github.com/TanStack/query/blob/main/packages/query-core/src/removable.ts#L41) +Defined in: packages/query-core/dist-ts/src/removable.d.ts:7 #### Returns @@ -162,7 +162,7 @@ Removable.clearGcTimeout continue(): Promise; ``` -Defined in: [packages/query-core/src/mutation.ts:243](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutation.ts#L243) +Defined in: packages/query-core/dist-ts/src/mutation.d.ts:139 Resumes a mutation that is currently paused or was restored from a dehydrated, still-`pending` state. @@ -199,11 +199,7 @@ await mutation?.continue() destroy(): void; ``` -Defined in: [packages/query-core/src/removable.ts:19](https://github.com/TanStack/query/blob/main/packages/query-core/src/removable.ts#L19) - -Clears the pending garbage collection timeout, so the entry is no longer scheduled for removal. -A subclass may override this to release what it holds on to as well — `Query` also cancels any -in-flight fetch. +Defined in: packages/query-core/dist-ts/src/removable.d.ts:4 #### Returns @@ -223,7 +219,7 @@ Removable.destroy execute(variables: TVariables): Promise; ``` -Defined in: [packages/query-core/src/mutation.ts:284](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutation.ts#L284) +Defined in: packages/query-core/dist-ts/src/mutation.d.ts:170 Runs the mutation function for the given variables through a retryer, and drives the mutation's state and lifecycle callbacks through to settlement. @@ -275,7 +271,7 @@ const data = await mutation.execute(variables) protected optionalRemove(): void; ``` -Defined in: [packages/query-core/src/mutation.ts:212](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutation.ts#L212) +Defined in: packages/query-core/dist-ts/src/mutation.d.ts:117 #### Returns @@ -295,7 +291,7 @@ Removable.optionalRemove protected scheduleGc(): void; ``` -Defined in: [packages/query-core/src/removable.ts:23](https://github.com/TanStack/query/blob/main/packages/query-core/src/removable.ts#L23) +Defined in: packages/query-core/dist-ts/src/removable.d.ts:5 #### Returns @@ -315,7 +311,7 @@ Removable.scheduleGc protected updateGcTime(newGcTime: number | undefined): void; ``` -Defined in: [packages/query-core/src/removable.ts:33](https://github.com/TanStack/query/blob/main/packages/query-core/src/removable.ts#L33) +Defined in: packages/query-core/dist-ts/src/removable.d.ts:6 #### Parameters diff --git a/docs/framework/angular/reference/classes/MutationCache.md b/docs/framework/angular/reference/classes/MutationCache.md index b64b17cf0e9..54f3e492d55 100644 --- a/docs/framework/angular/reference/classes/MutationCache.md +++ b/docs/framework/angular/reference/classes/MutationCache.md @@ -3,7 +3,7 @@ id: MutationCache title: MutationCache --- -Defined in: [packages/query-core/src/mutationCache.ts:124](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationCache.ts#L124) +Defined in: packages/query-core/dist-ts/src/mutationCache.d.ts:75 The `MutationCache` is the storage for mutations. @@ -28,16 +28,16 @@ const unsubscribe = mutationCache.subscribe((event) => { ### Constructor ```ts -new MutationCache(config: MutationCacheConfig): MutationCache; +new MutationCache(config?: MutationCacheConfig): MutationCache; ``` -Defined in: [packages/query-core/src/mutationCache.ts:129](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationCache.ts#L129) +Defined in: packages/query-core/dist-ts/src/mutationCache.d.ts:78 #### Parameters -##### config +##### config? -[`MutationCacheConfig`](../interfaces/MutationCacheConfig.md) = `{}` +[`MutationCacheConfig`](../interfaces/MutationCacheConfig.md) #### Returns @@ -54,10 +54,10 @@ Subscribable.constructor ### config ```ts -config: MutationCacheConfig = {}; +config: MutationCacheConfig; ``` -Defined in: [packages/query-core/src/mutationCache.ts:129](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationCache.ts#L129) +Defined in: packages/query-core/dist-ts/src/mutationCache.d.ts:77 *** @@ -67,7 +67,7 @@ Defined in: [packages/query-core/src/mutationCache.ts:129](https://github.com/Ta protected listeners: Set; ``` -Defined in: [packages/query-core/src/subscribable.ts:7](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L7) +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:2 #### Inherited from @@ -83,7 +83,7 @@ Subscribable.listeners clear(): void; ``` -Defined in: [packages/query-core/src/mutationCache.ts:236](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationCache.ts#L236) +Defined in: packages/query-core/dist-ts/src/mutationCache.d.ts:99 Removes all mutations from the cache. @@ -109,7 +109,7 @@ find(filters: MutationFilters): | undefined; ``` -Defined in: [packages/query-core/src/mutationCache.ts:278](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationCache.ts#L278) +Defined in: packages/query-core/dist-ts/src/mutationCache.d.ts:129 A slightly more advanced method that can be used to get an existing mutation instance from the cache. If the mutation does not exist, `undefined` is returned. @@ -163,10 +163,10 @@ const mutation = mutationCache.find({ mutationKey: ['addPost'] }) ### findAll() ```ts -findAll(filters: MutationFilters): Mutation[]; +findAll(filters?: MutationFilters): Mutation[]; ``` -Defined in: [packages/query-core/src/mutationCache.ts:308](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationCache.ts#L308) +Defined in: packages/query-core/dist-ts/src/mutationCache.d.ts:145 An even more advanced method that can be used to get existing mutation instances from the cache that match the given filters. If no mutations match, an empty array is returned. @@ -176,9 +176,9 @@ information about mutations in rare scenarios. #### Parameters -##### filters +##### filters? -[`MutationFilters`](../interfaces/MutationFilters.md) = `{}` +[`MutationFilters`](../interfaces/MutationFilters.md)\<`unknown`, `Error`, `unknown`, `unknown`\> #### Returns @@ -204,7 +204,7 @@ const mutations = mutationCache.findAll({ mutationKey: ['addPost'] }) getAll(): Mutation[]; ``` -Defined in: [packages/query-core/src/mutationCache.ts:259](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationCache.ts#L259) +Defined in: packages/query-core/dist-ts/src/mutationCache.d.ts:113 Returns all mutations within the cache. @@ -231,9 +231,7 @@ const mutations = mutationCache.getAll() hasListeners(): boolean; ``` -Defined in: [packages/query-core/src/subscribable.ts:41](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L41) - -Returns `true` while at least one listener is registered, `false` once they have all unsubscribed. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:5 #### Returns @@ -253,7 +251,7 @@ Subscribable.hasListeners protected onSubscribe(): void; ``` -Defined in: [packages/query-core/src/subscribable.ts:45](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L45) +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:6 #### Returns @@ -273,7 +271,7 @@ Subscribable.onSubscribe protected onUnsubscribe(): void; ``` -Defined in: [packages/query-core/src/subscribable.ts:49](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L49) +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:7 #### Returns @@ -293,11 +291,7 @@ Subscribable.onUnsubscribe subscribe(listener: MutationCacheListener): () => void; ``` -Defined in: [packages/query-core/src/subscribable.ts:27](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L27) - -Registers a listener to be called on every update this object notifies about. Returns a function -that removes the listener again — call it to stop listening. The base class never drops a listener -on its own, though some subclasses clear all of theirs in `destroy()`. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:4 #### Parameters diff --git a/docs/framework/angular/reference/classes/MutationObserver.md b/docs/framework/angular/reference/classes/MutationObserver.md index e8ba6146fb3..9c8f8b30daf 100644 --- a/docs/framework/angular/reference/classes/MutationObserver.md +++ b/docs/framework/angular/reference/classes/MutationObserver.md @@ -3,7 +3,7 @@ id: MutationObserver title: MutationObserver --- -Defined in: [packages/query-core/src/mutationObserver.ts:38](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationObserver.ts#L38) +Defined in: packages/query-core/dist-ts/src/mutationObserver.d.ts:21 Observes a single mutation and derives a `MutationObserverResult` from it. A framework hook like `useMutation` creates one `MutationObserver` per hook @@ -50,7 +50,7 @@ const observer = new MutationObserver(queryClient, { new MutationObserver(client: QueryClient, options: MutationObserverOptions): MutationObserver; ``` -Defined in: [packages/query-core/src/mutationObserver.ts:58](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationObserver.ts#L58) +Defined in: packages/query-core/dist-ts/src/mutationObserver.d.ts:24 #### Parameters @@ -69,9 +69,7 @@ Defined in: [packages/query-core/src/mutationObserver.ts:58](https://github.com/ #### Overrides ```ts -Subscribable< - MutationObserverListener ->.constructor +Subscribable>.constructor ``` ## Properties @@ -82,7 +80,7 @@ Subscribable< protected listeners: Set>; ``` -Defined in: [packages/query-core/src/subscribable.ts:7](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L7) +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:2 #### Inherited from @@ -98,7 +96,7 @@ Subscribable.listeners options: MutationObserverOptions; ``` -Defined in: [packages/query-core/src/mutationObserver.ts:46](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationObserver.ts#L46) +Defined in: packages/query-core/dist-ts/src/mutationObserver.d.ts:23 ## Methods @@ -108,7 +106,7 @@ Defined in: [packages/query-core/src/mutationObserver.ts:46](https://github.com/ protected bindMethods(): void; ``` -Defined in: [packages/query-core/src/mutationObserver.ts:75](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationObserver.ts#L75) +Defined in: packages/query-core/dist-ts/src/mutationObserver.d.ts:25 #### Returns @@ -122,7 +120,7 @@ Defined in: [packages/query-core/src/mutationObserver.ts:75](https://github.com/ getCurrentResult(): MutationObserverResult; ``` -Defined in: [packages/query-core/src/mutationObserver.ts:155](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationObserver.ts#L155) +Defined in: packages/query-core/dist-ts/src/mutationObserver.d.ts:52 Returns the observer's current result, derived from the observed mutation's state (or the default, `idle` state if no mutation has been @@ -140,9 +138,7 @@ built yet, e.g. before the first `mutate()` call or after `reset()`). hasListeners(): boolean; ``` -Defined in: [packages/query-core/src/subscribable.ts:41](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L41) - -Returns `true` while at least one listener is registered, `false` once they have all unsubscribed. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:5 #### Returns @@ -162,7 +158,7 @@ Subscribable.hasListeners mutate(variables: TVariables, options?: MutateOptions): Promise; ``` -Defined in: [packages/query-core/src/mutationObserver.ts:207](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationObserver.ts#L207) +Defined in: packages/query-core/dist-ts/src/mutationObserver.d.ts:88 Builds a new `Mutation` in the `MutationCache` using the observer's current options, detaches this observer from any previously observed @@ -204,7 +200,7 @@ await observer.mutate( protected onSubscribe(): void; ``` -Defined in: [packages/query-core/src/mutationObserver.ts:127](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationObserver.ts#L127) +Defined in: packages/query-core/dist-ts/src/mutationObserver.d.ts:43 #### Returns @@ -224,7 +220,7 @@ Subscribable.onSubscribe protected onUnsubscribe(): void; ``` -Defined in: [packages/query-core/src/mutationObserver.ts:135](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationObserver.ts#L135) +Defined in: packages/query-core/dist-ts/src/mutationObserver.d.ts:44 #### Returns @@ -244,7 +240,7 @@ Subscribable.onUnsubscribe reset(): void; ``` -Defined in: [packages/query-core/src/mutationObserver.ts:180](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationObserver.ts#L180) +Defined in: packages/query-core/dist-ts/src/mutationObserver.d.ts:69 Detaches the observer from the mutation it is currently observing (if any) and resets the observed result back to its default, `idle` state. @@ -276,7 +272,7 @@ observer.reset() setOptions(options: MutationObserverOptions): void; ``` -Defined in: [packages/query-core/src/mutationObserver.ts:96](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationObserver.ts#L96) +Defined in: packages/query-core/dist-ts/src/mutationObserver.d.ts:42 Updates the observer's options. @@ -312,11 +308,7 @@ observer.setOptions({ subscribe(listener: MutationObserverListener): () => void; ``` -Defined in: [packages/query-core/src/subscribable.ts:27](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L27) - -Registers a listener to be called on every update this object notifies about. Returns a function -that removes the listener again — call it to stop listening. The base class never drops a listener -on its own, though some subclasses clear all of theirs in `destroy()`. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:4 #### Parameters diff --git a/docs/framework/angular/reference/classes/QueriesObserver.md b/docs/framework/angular/reference/classes/QueriesObserver.md index ebcbcd9cc97..3aafd8b746e 100644 --- a/docs/framework/angular/reference/classes/QueriesObserver.md +++ b/docs/framework/angular/reference/classes/QueriesObserver.md @@ -3,7 +3,7 @@ id: QueriesObserver title: QueriesObserver --- -Defined in: [packages/query-core/src/queriesObserver.ts:56](https://github.com/TanStack/query/blob/main/packages/query-core/src/queriesObserver.ts#L56) +Defined in: packages/query-core/dist-ts/src/queriesObserver.d.ts:37 A `QueriesObserver` watches an array of queries at once, exposing them as a single array of `QueryObserverResult`s (or, when a `combine` option is @@ -45,7 +45,7 @@ new QueriesObserver( options?: QueriesObserverOptions): QueriesObserver; ``` -Defined in: [packages/query-core/src/queriesObserver.ts:70](https://github.com/TanStack/query/blob/main/packages/query-core/src/queriesObserver.ts#L70) +Defined in: packages/query-core/dist-ts/src/queriesObserver.d.ts:39 #### Parameters @@ -79,7 +79,7 @@ Subscribable.constructor protected listeners: Set; ``` -Defined in: [packages/query-core/src/subscribable.ts:7](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L7) +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:2 #### Inherited from @@ -95,7 +95,7 @@ Subscribable.listeners destroy(): void; ``` -Defined in: [packages/query-core/src/queriesObserver.ts:106](https://github.com/TanStack/query/blob/main/packages/query-core/src/queriesObserver.ts#L106) +Defined in: packages/query-core/dist-ts/src/queriesObserver.d.ts:46 Stops observing all queries: clears all listeners and destroys every underlying `QueryObserver` this observer manages. @@ -112,7 +112,7 @@ underlying `QueryObserver` this observer manages. getCurrentResult(): QueryObserverResult[]; ``` -Defined in: [packages/query-core/src/queriesObserver.ts:210](https://github.com/TanStack/query/blob/main/packages/query-core/src/queriesObserver.ts#L210) +Defined in: packages/query-core/dist-ts/src/queriesObserver.d.ts:73 Returns the most recently computed array of `QueryObserverResult`s, one per observed query, in the same order as the queries passed to the @@ -137,7 +137,7 @@ const data = results.map((result) => result.data) getObservers(): QueryObserver[]; ``` -Defined in: [packages/query-core/src/queriesObserver.ts:227](https://github.com/TanStack/query/blob/main/packages/query-core/src/queriesObserver.ts#L227) +Defined in: packages/query-core/dist-ts/src/queriesObserver.d.ts:84 Returns the underlying `QueryObserver` instances this observer manages, in the same order as the queries passed to the constructor or @@ -155,7 +155,7 @@ in the same order as the queries passed to the constructor or getOptimisticResult(queries: QueryObserverOptions[], combine: CombineFn | undefined): [QueryObserverResult[], (r?: QueryObserverResult[]) => TCombinedResult, () => QueryObserverResult[]]; ``` -Defined in: [packages/query-core/src/queriesObserver.ts:238](https://github.com/TanStack/query/blob/main/packages/query-core/src/queriesObserver.ts#L238) +Defined in: packages/query-core/dist-ts/src/queriesObserver.d.ts:92 The `QueriesObserver` counterpart of [QueryObserver#getOptimisticResult](QueryObserver.md#getoptimisticresult) — computes the result for the given (already-defaulted) queries right now, synchronously. Called by @@ -185,7 +185,7 @@ wrap the results for property-access tracking. getQueries(): Query[]; ``` -Defined in: [packages/query-core/src/queriesObserver.ts:218](https://github.com/TanStack/query/blob/main/packages/query-core/src/queriesObserver.ts#L218) +Defined in: packages/query-core/dist-ts/src/queriesObserver.d.ts:78 Returns the underlying `Query` instances currently being observed, in the same order as the queries passed to the constructor or `setQueries`. @@ -202,9 +202,7 @@ the same order as the queries passed to the constructor or `setQueries`. hasListeners(): boolean; ``` -Defined in: [packages/query-core/src/subscribable.ts:41](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L41) - -Returns `true` while at least one listener is registered, `false` once they have all unsubscribed. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:5 #### Returns @@ -224,7 +222,7 @@ Subscribable.hasListeners protected onSubscribe(): void; ``` -Defined in: [packages/query-core/src/queriesObserver.ts:86](https://github.com/TanStack/query/blob/main/packages/query-core/src/queriesObserver.ts#L86) +Defined in: packages/query-core/dist-ts/src/queriesObserver.d.ts:40 #### Returns @@ -244,7 +242,7 @@ Subscribable.onSubscribe protected onUnsubscribe(): void; ``` -Defined in: [packages/query-core/src/queriesObserver.ts:96](https://github.com/TanStack/query/blob/main/packages/query-core/src/queriesObserver.ts#L96) +Defined in: packages/query-core/dist-ts/src/queriesObserver.d.ts:41 #### Returns @@ -264,7 +262,7 @@ Subscribable.onUnsubscribe setQueries(queries: QueryObserverOptions[], options?: QueriesObserverOptions): void; ``` -Defined in: [packages/query-core/src/queriesObserver.ts:127](https://github.com/TanStack/query/blob/main/packages/query-core/src/queriesObserver.ts#L127) +Defined in: packages/query-core/dist-ts/src/queriesObserver.d.ts:61 Replaces the set of queries being observed. Existing `QueryObserver`s are reused for queries that match an already-observed query hash; @@ -302,11 +300,7 @@ observer.setQueries([ subscribe(listener: QueriesObserverListener): () => void; ``` -Defined in: [packages/query-core/src/subscribable.ts:27](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L27) - -Registers a listener to be called on every update this object notifies about. Returns a function -that removes the listener again — call it to stop listening. The base class never drops a listener -on its own, though some subclasses clear all of theirs in `destroy()`. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:4 #### Parameters diff --git a/docs/framework/angular/reference/classes/Query.md b/docs/framework/angular/reference/classes/Query.md index 646028952e1..214b1f36464 100644 --- a/docs/framework/angular/reference/classes/Query.md +++ b/docs/framework/angular/reference/classes/Query.md @@ -3,7 +3,7 @@ id: Query title: Query --- -Defined in: [packages/query-core/src/query.ts:225](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L225) +Defined in: packages/query-core/dist-ts/src/query.d.ts:154 Represents a single cached query. A `Query` holds the query's key, options, state (data/error/status), and the observers currently subscribed to it. @@ -54,7 +54,7 @@ if (query) { new Query(config: QueryConfig): Query; ``` -Defined in: [packages/query-core/src/query.ts:246](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L246) +Defined in: packages/query-core/dist-ts/src/query.d.ts:161 #### Parameters @@ -80,7 +80,7 @@ Removable.constructor gcTime: number; ``` -Defined in: [packages/query-core/src/removable.ts:11](https://github.com/TanStack/query/blob/main/packages/query-core/src/removable.ts#L11) +Defined in: packages/query-core/dist-ts/src/removable.d.ts:3 #### Inherited from @@ -96,7 +96,7 @@ Removable.gcTime observers: QueryObserver[]; ``` -Defined in: [packages/query-core/src/query.ts:242](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L242) +Defined in: packages/query-core/dist-ts/src/query.d.ts:160 *** @@ -106,7 +106,7 @@ Defined in: [packages/query-core/src/query.ts:242](https://github.com/TanStack/q options: QueryOptions; ``` -Defined in: [packages/query-core/src/query.ts:233](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L233) +Defined in: packages/query-core/dist-ts/src/query.d.ts:158 *** @@ -116,7 +116,7 @@ Defined in: [packages/query-core/src/query.ts:233](https://github.com/TanStack/q queryHash: string; ``` -Defined in: [packages/query-core/src/query.ts:232](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L232) +Defined in: packages/query-core/dist-ts/src/query.d.ts:157 *** @@ -126,7 +126,7 @@ Defined in: [packages/query-core/src/query.ts:232](https://github.com/TanStack/q queryKey: TQueryKey; ``` -Defined in: [packages/query-core/src/query.ts:231](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L231) +Defined in: packages/query-core/dist-ts/src/query.d.ts:156 *** @@ -136,7 +136,7 @@ Defined in: [packages/query-core/src/query.ts:231](https://github.com/TanStack/q state: QueryState; ``` -Defined in: [packages/query-core/src/query.ts:234](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L234) +Defined in: packages/query-core/dist-ts/src/query.d.ts:159 ## Accessors @@ -148,7 +148,7 @@ Defined in: [packages/query-core/src/query.ts:234](https://github.com/TanStack/q get meta(): Record | undefined; ``` -Defined in: [packages/query-core/src/query.ts:264](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L264) +Defined in: packages/query-core/dist-ts/src/query.d.ts:165 The `meta` object passed in the query's options, if any. @@ -166,7 +166,7 @@ The `meta` object passed in the query's options, if any. get promise(): Promise | undefined; ``` -Defined in: [packages/query-core/src/query.ts:277](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L277) +Defined in: packages/query-core/dist-ts/src/query.d.ts:172 The promise for the currently in-flight fetch, if the query is fetching. `undefined` when the query is not fetching. @@ -183,7 +183,7 @@ The promise for the currently in-flight fetch, if the query is fetching. cancel(options?: CancelOptions): Promise; ``` -Defined in: [packages/query-core/src/query.ts:348](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L348) +Defined in: packages/query-core/dist-ts/src/query.d.ts:196 Cancels the query's currently in-flight fetch, if any. - Returns a promise that resolves once the cancellation has settled. @@ -213,7 +213,7 @@ await query.cancel() protected clearGcTimeout(): void; ``` -Defined in: [packages/query-core/src/removable.ts:41](https://github.com/TanStack/query/blob/main/packages/query-core/src/removable.ts#L41) +Defined in: packages/query-core/dist-ts/src/removable.d.ts:7 #### Returns @@ -233,7 +233,7 @@ Removable.clearGcTimeout destroy(): void; ``` -Defined in: [packages/query-core/src/query.ts:361](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L361) +Defined in: packages/query-core/dist-ts/src/query.d.ts:204 Clears the query's garbage collection timeout and silently cancels any in-flight fetch. Called by `QueryCache` when the query is removed from @@ -261,7 +261,7 @@ Removable.destroy fetch(options?: QueryOptions, fetchOptions?: FetchOptions): Promise; ``` -Defined in: [packages/query-core/src/query.ts:590](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L590) +Defined in: packages/query-core/dist-ts/src/query.d.ts:309 Fetches the query, i.e. runs its `queryFn` (through any configured retryer/behavior) and updates the query's state with the result. @@ -294,7 +294,7 @@ retryer/behavior) and updates the query's state with the result. getObserversCount(): number; ``` -Defined in: [packages/query-core/src/query.ts:560](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L560) +Defined in: packages/query-core/dist-ts/src/query.d.ts:287 Returns the number of observers currently subscribed to this query. @@ -318,7 +318,7 @@ if (query.getObserversCount() === 0) { invalidate(): void; ``` -Defined in: [packages/query-core/src/query.ts:574](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L574) +Defined in: packages/query-core/dist-ts/src/query.d.ts:298 Marks the query as invalidated, unless it is already invalidated. This updates `state.isInvalidated` and notifies observers, but does not by @@ -342,7 +342,7 @@ query.invalidate() isActive(): boolean; ``` -Defined in: [packages/query-core/src/query.ts:386](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L386) +Defined in: packages/query-core/dist-ts/src/query.d.ts:217 Returns `true` if the query has at least one observer for which `enabled` does not resolve to `false`. @@ -359,7 +359,7 @@ does not resolve to `false`. isDisabled(): boolean; ``` -Defined in: [packages/query-core/src/query.ts:400](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L400) +Defined in: packages/query-core/dist-ts/src/query.d.ts:226 Returns `true` if the query is disabled, meaning it will not fetch automatically. @@ -380,7 +380,7 @@ automatically. isFetched(): boolean; ``` -Defined in: [packages/query-core/src/query.ts:412](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L412) +Defined in: packages/query-core/dist-ts/src/query.d.ts:231 Returns `true` if the query has been fetched, i.e. it has resolved with either data or an error at least once. @@ -397,7 +397,7 @@ either data or an error at least once. isStale(): boolean; ``` -Defined in: [packages/query-core/src/query.ts:447](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L447) +Defined in: packages/query-core/dist-ts/src/query.d.ts:253 Returns `true` if the query is stale. - If the query has observers, defers to whether any observer's current @@ -427,10 +427,10 @@ if (query.isStale()) { ### isStaleByTime() ```ts -isStaleByTime(staleTime: number | "static"): boolean; +isStaleByTime(staleTime?: StaleTime): boolean; ``` -Defined in: [packages/query-core/src/query.ts:473](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L473) +Defined in: packages/query-core/dist-ts/src/query.d.ts:268 Returns `true` if the query's data is stale relative to the given `staleTime` (defaults to `0`). @@ -441,9 +441,9 @@ Returns `true` if the query's data is stale relative to the given #### Parameters -##### staleTime +##### staleTime? -`number` | `"static"` +[`StaleTime`](../type-aliases/StaleTime.md) #### Returns @@ -467,7 +467,7 @@ const isStale = query.isStaleByTime(1000 * 60) isStatic(): boolean; ``` -Defined in: [packages/query-core/src/query.ts:420](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L420) +Defined in: packages/query-core/dist-ts/src/query.d.ts:236 Returns `true` if the query has at least one observer configured with `staleTime: 'static'`, meaning it is treated as never stale. @@ -484,7 +484,7 @@ Returns `true` if the query has at least one observer configured with protected optionalRemove(): void; ``` -Defined in: [packages/query-core/src/query.ts:305](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L305) +Defined in: packages/query-core/dist-ts/src/query.d.ts:175 #### Returns @@ -504,7 +504,7 @@ Removable.optionalRemove reset(): void; ``` -Defined in: [packages/query-core/src/query.ts:377](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L377) +Defined in: packages/query-core/dist-ts/src/query.d.ts:212 Resets the query back to its initial state (the state it had when it was first created, e.g. any `initialData`), destroying it first to cancel any @@ -522,7 +522,7 @@ in-flight fetch. protected scheduleGc(): void; ``` -Defined in: [packages/query-core/src/removable.ts:23](https://github.com/TanStack/query/blob/main/packages/query-core/src/removable.ts#L23) +Defined in: packages/query-core/dist-ts/src/removable.d.ts:5 #### Returns @@ -542,7 +542,7 @@ Removable.scheduleGc setState(state: Partial>): void; ``` -Defined in: [packages/query-core/src/query.ts:334](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L334) +Defined in: packages/query-core/dist-ts/src/query.d.ts:185 Merges the given partial state directly into this query's state, notifying observers. Used by persistence and broadcast plugins to restore a state snapshot, and by devtools to let a @@ -566,7 +566,7 @@ user manually trigger a loading/error state or edit the cached data. protected updateGcTime(newGcTime: number | undefined): void; ``` -Defined in: [packages/query-core/src/removable.ts:33](https://github.com/TanStack/query/blob/main/packages/query-core/src/removable.ts#L33) +Defined in: packages/query-core/dist-ts/src/removable.d.ts:6 #### Parameters diff --git a/docs/framework/angular/reference/classes/QueryCache.md b/docs/framework/angular/reference/classes/QueryCache.md index 18520030db7..f55d9dbb86c 100644 --- a/docs/framework/angular/reference/classes/QueryCache.md +++ b/docs/framework/angular/reference/classes/QueryCache.md @@ -3,7 +3,7 @@ id: QueryCache title: QueryCache --- -Defined in: [packages/query-core/src/queryCache.ts:123](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryCache.ts#L123) +Defined in: packages/query-core/dist-ts/src/queryCache.d.ts:85 The `QueryCache` is the storage mechanism for TanStack Query. It stores all the data, meta information, and state of the queries it contains. @@ -31,16 +31,16 @@ const unsubscribe = queryCache.subscribe((event) => { ### Constructor ```ts -new QueryCache(config: QueryCacheConfig): QueryCache; +new QueryCache(config?: QueryCacheConfig): QueryCache; ``` -Defined in: [packages/query-core/src/queryCache.ts:126](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryCache.ts#L126) +Defined in: packages/query-core/dist-ts/src/queryCache.d.ts:88 #### Parameters -##### config +##### config? -[`QueryCacheConfig`](../interfaces/QueryCacheConfig.md) = `{}` +[`QueryCacheConfig`](../interfaces/QueryCacheConfig.md) #### Returns @@ -57,10 +57,10 @@ Subscribable.constructor ### config ```ts -config: QueryCacheConfig = {}; +config: QueryCacheConfig; ``` -Defined in: [packages/query-core/src/queryCache.ts:126](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryCache.ts#L126) +Defined in: packages/query-core/dist-ts/src/queryCache.d.ts:87 *** @@ -70,7 +70,7 @@ Defined in: [packages/query-core/src/queryCache.ts:126](https://github.com/TanSt protected listeners: Set; ``` -Defined in: [packages/query-core/src/subscribable.ts:7](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L7) +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:2 #### Inherited from @@ -89,7 +89,7 @@ build( state?: QueryState): Query; ``` -Defined in: [packages/query-core/src/queryCache.ts:147](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryCache.ts#L147) +Defined in: packages/query-core/dist-ts/src/queryCache.d.ts:105 Returns the existing `Query` instance for the given options' `queryKey`/`queryHash`, or builds and adds a new one to the cache if none exists yet. Used by framework adapters and @@ -151,7 +151,7 @@ const query = queryCache.build(queryClient, { clear(): void; ``` -Defined in: [packages/query-core/src/queryCache.ts:228](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryCache.ts#L228) +Defined in: packages/query-core/dist-ts/src/queryCache.d.ts:135 Removes all queries from the cache. @@ -177,7 +177,7 @@ find(filters: WithRequired): Query[]; +findAll(filters?: QueryFilters): Query[]; ``` -Defined in: [packages/query-core/src/queryCache.ts:320](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryCache.ts#L320) +Defined in: packages/query-core/dist-ts/src/queryCache.d.ts:196 An even more advanced method that can be used to get existing query instances from the cache that partially match a query key. If no queries match, an empty array is returned. @@ -243,9 +243,9 @@ information about queries in rare scenarios. #### Parameters -##### filters +##### filters? -[`QueryFilters`](../interfaces/QueryFilters.md)\<`any`\> = `{}` +[`QueryFilters`](../interfaces/QueryFilters.md)\<`any`\> #### Returns @@ -273,7 +273,7 @@ get(queryHash: string): | undefined; ``` -Defined in: [packages/query-core/src/queryCache.ts:250](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryCache.ts#L250) +Defined in: packages/query-core/dist-ts/src/queryCache.d.ts:150 Returns the `Query` instance stored under the given `queryHash`, or `undefined` if none exists. Unlike [QueryCache#find](#find), this looks up by the already-computed hash rather @@ -326,7 +326,7 @@ const query = queryCache.get(queryHash) getAll(): Query[]; ``` -Defined in: [packages/query-core/src/queryCache.ts:273](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryCache.ts#L273) +Defined in: packages/query-core/dist-ts/src/queryCache.d.ts:161 Returns all queries within the cache. @@ -350,9 +350,7 @@ const queries = queryCache.getAll() hasListeners(): boolean; ``` -Defined in: [packages/query-core/src/subscribable.ts:41](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L41) - -Returns `true` while at least one listener is registered, `false` once they have all unsubscribed. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:5 #### Returns @@ -372,7 +370,7 @@ Subscribable.hasListeners protected onSubscribe(): void; ``` -Defined in: [packages/query-core/src/subscribable.ts:45](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L45) +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:6 #### Returns @@ -392,7 +390,7 @@ Subscribable.onSubscribe protected onUnsubscribe(): void; ``` -Defined in: [packages/query-core/src/subscribable.ts:49](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L49) +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:7 #### Returns @@ -412,7 +410,7 @@ Subscribable.onUnsubscribe remove(query: Query): void; ``` -Defined in: [packages/query-core/src/queryCache.ts:208](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryCache.ts#L208) +Defined in: packages/query-core/dist-ts/src/queryCache.d.ts:124 Destroys the given `Query` and removes it from the cache, notifying subscribers with a `'removed'` event. A no-op if the query is no longer the one currently stored under its hash @@ -448,11 +446,7 @@ if (query) { subscribe(listener: QueryCacheListener): () => void; ``` -Defined in: [packages/query-core/src/subscribable.ts:27](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L27) - -Registers a listener to be called on every update this object notifies about. Returns a function -that removes the listener again — call it to stop listening. The base class never drops a listener -on its own, though some subclasses clear all of theirs in `destroy()`. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:4 #### Parameters diff --git a/docs/framework/angular/reference/classes/QueryClient.md b/docs/framework/angular/reference/classes/QueryClient.md index 1dcf71fbffb..6b6463f4193 100644 --- a/docs/framework/angular/reference/classes/QueryClient.md +++ b/docs/framework/angular/reference/classes/QueryClient.md @@ -3,7 +3,7 @@ id: QueryClient title: QueryClient --- -Defined in: [packages/query-core/src/queryClient.ts:79](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L79) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:24 `QueryClient` is used to interact with a cache of queries and mutations. It owns a `QueryCache` and a `MutationCache` (creating default ones if none are passed in) and holds @@ -28,16 +28,16 @@ await queryClient.query({ queryKey: ['posts'], queryFn: fetchPosts }) ### Constructor ```ts -new QueryClient(config: QueryClientConfig): QueryClient; +new QueryClient(config?: QueryClientConfig): QueryClient; ``` -Defined in: [packages/query-core/src/queryClient.ts:89](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L89) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:26 #### Parameters -##### config +##### config? -[`QueryClientConfig`](../interfaces/QueryClientConfig.md) = `{}` +[`QueryClientConfig`](../interfaces/QueryClientConfig.md) #### Returns @@ -51,7 +51,7 @@ Defined in: [packages/query-core/src/queryClient.ts:89](https://github.com/TanSt cancelQueries(filters?: QueryFilters, cancelOptions?: CancelOptions): Promise; ``` -Defined in: [packages/query-core/src/queryClient.ts:441](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L441) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:180 Cancels outgoing fetches for queries matching the given filters. Most useful when performing optimistic updates, since any outgoing refetch that resolves afterwards would otherwise @@ -74,7 +74,7 @@ The returned promise never rejects, even if individual cancellations fail. ##### cancelOptions? -[`CancelOptions`](../interfaces/CancelOptions.md) = `{}` +[`CancelOptions`](../interfaces/CancelOptions.md) #### Returns @@ -94,7 +94,7 @@ await queryClient.cancelQueries({ queryKey: ['posts'], exact: true }) clear(): void; ``` -Defined in: [packages/query-core/src/queryClient.ts:1096](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L1096) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:430 Clears both the query cache and the mutation cache this client is connected to. @@ -119,7 +119,7 @@ queryClient.clear() defaultMutationOptions(options?: T): T; ``` -Defined in: [packages/query-core/src/queryClient.ts:1070](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L1070) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:418 The mutation counterpart of [QueryClient#defaultQueryOptions](#defaultqueryoptions). Called by framework adapters (e.g. inside `useMutation`) to merge `queryClient.setMutationDefaults` for the @@ -152,7 +152,7 @@ defaultQueryOptions): DefaultedQueryObserverOptions; ``` -Defined in: [packages/query-core/src/queryClient.ts:983](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L983) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:411 Called by framework adapters (e.g. inside `useQuery`) to resolve the options passed by the caller into their final, defaulted form: merging `queryClient.setQueryDefaults` for the @@ -203,7 +203,7 @@ on top. A no-op if the options are already defaulted (`_defaulted: true`). ensureInfiniteQueryData(options: EnsureInfiniteQueryDataOptions): Promise>; ``` -Defined in: [packages/query-core/src/queryClient.ts:747](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L747) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:284 #### Type Parameters @@ -249,7 +249,7 @@ Use queryClient.infiniteQuery({ ...options, staleTime: 'static' }) instead. This ensureQueryData(options: EnsureQueryDataOptions): Promise; ``` -Defined in: [packages/query-core/src/queryClient.ts:198](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L198) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:78 #### Type Parameters @@ -291,7 +291,7 @@ Use queryClient.query({ ...options, staleTime: 'static' }) instead. This method fetchInfiniteQuery(options: FetchInfiniteQueryOptions): Promise>; ``` -Defined in: [packages/query-core/src/queryClient.ts:702](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L702) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:276 #### Type Parameters @@ -337,7 +337,7 @@ Use queryClient.infiniteQuery(options) instead. This method will be removed in t fetchQuery(options: FetchQueryOptions): Promise; ``` -Defined in: [packages/query-core/src/queryClient.ts:609](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L609) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:246 #### Type Parameters @@ -383,7 +383,7 @@ Use queryClient.query(options) instead. This method will be removed in the next getDefaultOptions(): DefaultOptions; ``` -Defined in: [packages/query-core/src/queryClient.ts:831](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L831) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:336 Returns the default options that were set when creating the client, or via [QueryClient#setDefaultOptions](#setdefaultoptions). @@ -409,7 +409,7 @@ const defaultOptions = queryClient.getDefaultOptions() getMutationCache(): MutationCache; ``` -Defined in: [packages/query-core/src/queryClient.ts:815](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L815) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:323 Returns the mutation cache this client is connected to. @@ -435,7 +435,7 @@ const mutations = mutationCache.findAll({ status: 'pending' }) getMutationDefaults(mutationKey: readonly unknown[]): OmitKeyof, "mutationKey">; ``` -Defined in: [packages/query-core/src/queryClient.ts:958](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L958) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:404 Returns the default options registered for mutations whose mutation key partially matches the given `mutationKey`, via [QueryClient#setMutationDefaults](#setmutationdefaults). If multiple registered @@ -465,7 +465,7 @@ const defaultOptions = queryClient.getMutationDefaults(['addPost']) getQueriesData(filters: TQueryFilters): [readonly unknown[], TQueryFnData | undefined][]; ``` -Defined in: [packages/query-core/src/queryClient.ts:244](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L244) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:96 Imperative (non-reactive) way to retrieve the cached data of multiple queries at once. Only queries matching the given filters are returned; if none match, an empty array is @@ -517,7 +517,7 @@ const data = queryClient.getQueriesData({ queryKey: ['posts'] }) getQueryCache(): QueryCache; ``` -Defined in: [packages/query-core/src/queryClient.ts:799](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L799) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:310 Returns the query cache this client is connected to. @@ -543,7 +543,7 @@ const queries = queryCache.findAll({ queryKey: ['posts'] }) getQueryData(queryKey: TTaggedQueryKey): TInferredQueryFnData | undefined; ``` -Defined in: [packages/query-core/src/queryClient.ts:184](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L184) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:74 Imperative (non-reactive) way to retrieve data for a QueryKey. Should only be used in callbacks or functions where reading the latest data is necessary, e.g. for optimistic updates. @@ -589,7 +589,7 @@ The cached data for the query, or `undefined` if no query with this key has been getQueryDefaults(queryKey: readonly unknown[]): OmitKeyof, "queryKey">; ``` -Defined in: [packages/query-core/src/queryClient.ts:901](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L901) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:381 Returns the default options registered for queries whose query key partially matches the given `queryKey`, via [QueryClient#setQueryDefaults](#setquerydefaults). If multiple registered defaults @@ -621,7 +621,7 @@ getQueryState(options: InfiniteQueryExecuteOptions): Promise[] ? InfiniteData : TData>; ``` -Defined in: [packages/query-core/src/queryClient.ts:676](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L676) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:272 Asynchronous method to fetch and cache an infinite query, resolving with an [InfiniteData](../interfaces/InfiniteData.md) object or throwing with the error. @@ -737,7 +737,7 @@ try { invalidateQueries(filters?: InvalidateQueryFilters, options?: InvalidateOptions): Promise; ``` -Defined in: [packages/query-core/src/queryClient.ts:469](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L469) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:194 Marks queries matching the given filters as invalidated. Unlike [QueryClient#removeQueries](#removequeries), invalidated queries stay in the cache. @@ -760,7 +760,7 @@ Unless `filters.refetchType` is `'none'`, matching queries are then refetched vi ##### options? -[`InvalidateOptions`](../interfaces/InvalidateOptions.md) = `{}` +[`InvalidateOptions`](../interfaces/InvalidateOptions.md) #### Returns @@ -780,7 +780,7 @@ await queryClient.invalidateQueries({ queryKey: ['posts'], refetchType: 'active' isFetching(filters?: TQueryFilters): number; ``` -Defined in: [packages/query-core/src/queryClient.ts:150](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L150) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:52 Returns the number of queries in the cache that are currently fetching, optionally matching a set of filters. This includes background-fetching, loading new pages, and @@ -818,7 +818,7 @@ if (queryClient.isFetching()) { isMutating(filters?: TMutationFilters): number; ``` -Defined in: [packages/query-core/src/queryClient.ts:168](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L168) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:64 Returns the number of mutations in the cache that are currently pending, optionally matching a set of filters. @@ -855,7 +855,7 @@ if (queryClient.isMutating()) { mount(): void; ``` -Defined in: [packages/query-core/src/queryClient.ts:104](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L104) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:33 Called by a framework adapter's `QueryClientProvider`-equivalent when it mounts, to start listening for focus/online events and resume paused mutations. Ref-counted via an internal @@ -874,7 +874,7 @@ the shared listeners until the last one unmounts. prefetchInfiniteQuery(options: FetchInfiniteQueryOptions): Promise; ``` -Defined in: [packages/query-core/src/queryClient.ts:725](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L725) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:280 #### Type Parameters @@ -920,7 +920,7 @@ Use queryClient.infiniteQuery(options) instead. You can swallow errors with `.ca prefetchQuery(options: FetchQueryOptions): Promise; ``` -Defined in: [packages/query-core/src/queryClient.ts:643](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L643) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:250 #### Type Parameters @@ -962,7 +962,7 @@ Use queryClient.query(options) instead. You can swallow errors with `.catch(noop query(options: QueryExecuteOptions): Promise; ``` -Defined in: [packages/query-core/src/queryClient.ts:563](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L563) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:242 Asynchronous method to fetch and cache a query, resolving with the data or throwing with the error. @@ -1039,7 +1039,7 @@ try { refetchQueries(filters?: RefetchQueryFilters, options?: RefetchOptions): Promise; ``` -Defined in: [packages/query-core/src/queryClient.ts:506](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L506) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:210 Refetches queries matching the given filters, regardless of whether they are stale. Without filters, every query in the cache is refetched. Queries that are disabled, or static (only @@ -1063,7 +1063,7 @@ not reject on individual query failures unless `throwOnError` is set. ##### options? -[`RefetchOptions`](../interfaces/RefetchOptions.md) = `{}` +[`RefetchOptions`](../interfaces/RefetchOptions.md) #### Returns @@ -1084,7 +1084,7 @@ await queryClient.refetchQueries({ queryKey: ['posts'], type: 'active' }) removeQueries(filters?: QueryFilters): void; ``` -Defined in: [packages/query-core/src/queryClient.ts:385](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L385) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:155 Removes queries from the cache that match the given filters. Unlike [QueryClient#invalidateQueries](#invalidatequeries) or [QueryClient#refetchQueries](#refetchqueries), this removes @@ -1121,7 +1121,7 @@ queryClient.removeQueries({ queryKey: ['posts'], exact: true }) resetQueries(filters?: QueryFilters, options?: ResetOptions): Promise; ``` -Defined in: [packages/query-core/src/queryClient.ts:406](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L406) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:166 Resets queries matching the given filters back to their initial state (e.g. any `initialData`), notifying subscribers rather than removing them. Active queries among the @@ -1161,7 +1161,7 @@ await queryClient.resetQueries({ queryKey: ['posts'], exact: true }) resumePausedMutations(): Promise; ``` -Defined in: [packages/query-core/src/queryClient.ts:780](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L780) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:297 Resumes mutations that were paused because there was no network connection. Does nothing (resolving immediately) if the client is currently offline. @@ -1187,7 +1187,7 @@ await queryClient.resumePausedMutations() setDefaultOptions(options: DefaultOptions): void; ``` -Defined in: [packages/query-core/src/queryClient.ts:852](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L852) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:354 Dynamically sets the default options for this client, overwriting any previously defined default options. @@ -1227,7 +1227,7 @@ queryClient.setDefaultOptions({ setMutationDefaults(mutationKey: readonly unknown[], options: OmitKeyof, "mutationKey">): void; ``` -Defined in: [packages/query-core/src/queryClient.ts:930](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L930) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:393 Sets default options for mutations whose mutation key partially matches the given `mutationKey`. As with [QueryClient#setQueryDefaults](#setquerydefaults), the order of registration @@ -1286,7 +1286,7 @@ setQueriesData( options?: SetDataOptions): [readonly unknown[], TQueryFnData | undefined][]; ``` -Defined in: [packages/query-core/src/queryClient.ts:328](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L328) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:132 Synchronous way to immediately update the cached data of multiple queries at once, using filters or partial query key matching. Only queries that already exist and match the given @@ -1343,7 +1343,7 @@ setQueryData( options?: SetDataOptions): NoInfer | undefined; ``` -Defined in: [packages/query-core/src/queryClient.ts:278](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L278) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:118 Synchronous way to immediately update a query's cached data. If the updater (or the value passed) resolves to `undefined`, the cache is left untouched and no query is created; @@ -1412,7 +1412,7 @@ queryClient.setQueryData(['posts'], (oldPosts) => [...oldPosts, newPost]) setQueryDefaults(queryKey: readonly unknown[], options: Partial, "queryKey">>): void; ``` -Defined in: [packages/query-core/src/queryClient.ts:871](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L871) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:370 Sets default options for queries whose query key partially matches the given `queryKey`. @@ -1469,7 +1469,7 @@ await queryClient.query({ queryKey: ['posts'] }) unmount(): void; ``` -Defined in: [packages/query-core/src/queryClient.ts:127](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L127) +Defined in: packages/query-core/dist-ts/src/queryClient.d.ts:39 The inverse of [QueryClient#mount](#mount) — called by a framework adapter's `QueryClientProvider`-equivalent when it unmounts. Only tears down the focus/online diff --git a/docs/framework/angular/reference/classes/QueryObserver.md b/docs/framework/angular/reference/classes/QueryObserver.md index ba20c873925..a3e0b017e0e 100644 --- a/docs/framework/angular/reference/classes/QueryObserver.md +++ b/docs/framework/angular/reference/classes/QueryObserver.md @@ -3,7 +3,7 @@ id: QueryObserver title: QueryObserver --- -Defined in: [packages/query-core/src/queryObserver.ts:57](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L57) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:29 A `QueryObserver` watches a single query in the `QueryCache` and computes a `QueryObserverResult` from its state, recomputing and notifying subscribers @@ -63,7 +63,7 @@ const unsubscribe = observer.subscribe((result) => { new QueryObserver(client: QueryClient, options: QueryObserverOptions): QueryObserver; ``` -Defined in: [packages/query-core/src/queryObserver.ts:87](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L87) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:32 #### Parameters @@ -93,7 +93,7 @@ Subscribable>.constructor protected listeners: Set>; ``` -Defined in: [packages/query-core/src/subscribable.ts:7](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L7) +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:2 #### Inherited from @@ -109,7 +109,7 @@ Subscribable.listeners options: QueryObserverOptions; ``` -Defined in: [packages/query-core/src/queryObserver.ts:89](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L89) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:31 ## Methods @@ -119,7 +119,7 @@ Defined in: [packages/query-core/src/queryObserver.ts:89](https://github.com/Tan protected bindMethods(): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:106](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L106) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:33 #### Returns @@ -133,7 +133,7 @@ Defined in: [packages/query-core/src/queryObserver.ts:106](https://github.com/Ta protected createResult(query: Query, options: QueryObserverOptions): QueryObserverResult; ``` -Defined in: [packages/query-core/src/queryObserver.ts:559](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L559) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:136 #### Parameters @@ -157,7 +157,7 @@ Defined in: [packages/query-core/src/queryObserver.ts:559](https://github.com/Ta destroy(): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:161](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L161) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:53 Stops observing the current query: clears all listeners, cancels the stale and refetch-interval timers, and removes this observer from the @@ -175,7 +175,7 @@ query it was observing. protected fetch(fetchOptions: ObserverFetchOptions): Promise>; ``` -Defined in: [packages/query-core/src/queryObserver.ts:448](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L448) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:135 #### Parameters @@ -195,7 +195,7 @@ Defined in: [packages/query-core/src/queryObserver.ts:448](https://github.com/Ta fetchOptimistic(options: QueryObserverOptions): Promise>; ``` -Defined in: [packages/query-core/src/queryObserver.ts:395](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L395) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:134 Fetches a query defined by the given options without affecting this observer's own tracked query or result, and returns a promise that @@ -231,7 +231,7 @@ console.log(result.data) getCurrentQuery(): Query; ``` -Defined in: [packages/query-core/src/queryObserver.ts:357](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L357) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:106 Returns the `Query` instance this observer is currently observing. @@ -247,7 +247,7 @@ Returns the `Query` instance this observer is currently observing. getCurrentResult(): QueryObserverResult; ``` -Defined in: [packages/query-core/src/queryObserver.ts:321](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L321) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:88 Returns the most recently computed `QueryObserverResult` for the observed query. This is a point-in-time read; to be notified of updates @@ -273,7 +273,7 @@ console.log(result.status, result.data) getOptimisticResult(options: DefaultedQueryObserverOptions): QueryObserverResult; ``` -Defined in: [packages/query-core/src/queryObserver.ts:272](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L272) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:75 Computes the result the observer would produce for the given (already-defaulted) options right now, building the underlying `Query` if it doesn't exist yet, without waiting for a @@ -298,9 +298,7 @@ returned value is available synchronously, ahead of `setOptions` triggering an a hasListeners(): boolean; ``` -Defined in: [packages/query-core/src/subscribable.ts:41](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L41) - -Returns `true` while at least one listener is registered, `false` once they have all unsubscribed. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:5 #### Returns @@ -320,7 +318,7 @@ Subscribable.hasListeners protected onSubscribe(): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:110](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L110) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:34 #### Returns @@ -340,7 +338,7 @@ Subscribable.onSubscribe protected onUnsubscribe(): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:124](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L124) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:35 #### Returns @@ -357,19 +355,19 @@ Subscribable.onUnsubscribe ### refetch() ```ts -refetch(__namedParameters: RefetchOptions): Promise>; +refetch(__namedParameters?: RefetchOptions): Promise>; ``` -Defined in: [packages/query-core/src/queryObserver.ts:371](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L371) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:117 Refetches the observed query and returns a promise that resolves with the resulting `QueryObserverResult`. #### Parameters -##### \_\_namedParameters +##### \_\_namedParameters? -[`RefetchOptions`](../interfaces/RefetchOptions.md) = `{}` +[`RefetchOptions`](../interfaces/RefetchOptions.md) #### Returns @@ -390,7 +388,7 @@ console.log(result.data) setOptions(options: QueryObserverOptions): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:182](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L182) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:68 Updates the observer's options. This will re-resolve the query being observed (switching to a different query if the `queryKey` changed), @@ -424,7 +422,7 @@ observer.setOptions({ queryKey: ['posts', 2], queryFn: () => fetchPost(2) }) shouldFetchOnReconnect(): boolean; ``` -Defined in: [packages/query-core/src/queryObserver.ts:135](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L135) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:41 Returns whether the observed query is currently stale and configured (via the `refetchOnReconnect` option) to refetch when the network @@ -442,7 +440,7 @@ reconnects. shouldFetchOnWindowFocus(): boolean; ``` -Defined in: [packages/query-core/src/queryObserver.ts:148](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L148) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:47 Returns whether the observed query is currently stale and configured (via the `refetchOnWindowFocus` option) to refetch when the window @@ -460,11 +458,7 @@ regains focus. subscribe(listener: QueryObserverListener): () => void; ``` -Defined in: [packages/query-core/src/subscribable.ts:27](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L27) - -Registers a listener to be called on every update this object notifies about. Returns a function -that removes the listener again — call it to stop listening. The base class never drops a listener -on its own, though some subclasses clear all of theirs in `destroy()`. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:4 #### Parameters @@ -506,8 +500,8 @@ Subscribable.subscribe ```ts trackProp(key: - | "error" | "data" + | "error" | "isError" | "isPending" | "isLoading" @@ -533,7 +527,7 @@ trackProp(key: | "fetchStatus"): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:350](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L350) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:102 Records that the given `QueryObserverResult` property was read, so a subsequent update only notifies this observer if a tracked property actually changed. Normally called indirectly via @@ -544,7 +538,7 @@ access themselves (e.g. through their own reactivity system) instead of via the ##### key -`"error"` | `"data"` | `"isError"` | `"isPending"` | `"isLoading"` | `"isLoadingError"` | `"isRefetchError"` | `"isSuccess"` | `"isPlaceholderData"` | `"status"` | `"dataUpdatedAt"` | `"errorUpdatedAt"` | `"failureCount"` | `"failureReason"` | `"errorUpdateCount"` | `"isFetched"` | `"isFetchedAfterMount"` | `"isFetching"` | `"isInitialLoading"` | `"isPaused"` | `"isRefetching"` | `"isStale"` | `"isEnabled"` | `"refetch"` | `"fetchStatus"` +`"data"` | `"error"` | `"isError"` | `"isPending"` | `"isLoading"` | `"isLoadingError"` | `"isRefetchError"` | `"isSuccess"` | `"isPlaceholderData"` | `"status"` | `"dataUpdatedAt"` | `"errorUpdatedAt"` | `"failureCount"` | `"failureReason"` | `"errorUpdateCount"` | `"isFetched"` | `"isFetchedAfterMount"` | `"isFetching"` | `"isInitialLoading"` | `"isPaused"` | `"isRefetching"` | `"isStale"` | `"isEnabled"` | `"refetch"` | `"fetchStatus"` #### Returns @@ -556,8 +550,8 @@ access themselves (e.g. through their own reactivity system) instead of via the ```ts trackResult(result: QueryObserverResult, onPropTracked?: (key: - | "error" | "data" + | "error" | "isError" | "isPending" | "isLoading" @@ -583,7 +577,7 @@ trackResult(result: QueryObserverResult, onPropTracked?: (key: | "fetchStatus") => void): QueryObserverResult; ``` -Defined in: [packages/query-core/src/queryObserver.ts:331](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L331) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:95 Wraps a `QueryObserverResult` in a `Proxy` that records which properties are read, via [QueryObserver#trackProp](#trackprop) (and an optional `onPropTracked` callback). Used by framework @@ -599,8 +593,8 @@ properties you actually read" behavior. ##### onPropTracked? (`key`: - \| `"error"` \| `"data"` + \| `"error"` \| `"isError"` \| `"isPending"` \| `"isLoading"` @@ -637,7 +631,7 @@ properties you actually read" behavior. updateResult(): void; ``` -Defined in: [packages/query-core/src/queryObserver.ts:735](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryObserver.ts#L735) +Defined in: packages/query-core/dist-ts/src/queryObserver.d.ts:142 Recomputes and stores the current result from the current query/options, notifying listeners if it changed. Framework adapters call this right after subscribing to make sure no query diff --git a/docs/framework/angular/reference/functions/defaultShouldDehydrateMutation.md b/docs/framework/angular/reference/functions/defaultShouldDehydrateMutation.md index 0458c88f4fc..38c1127b2c7 100644 --- a/docs/framework/angular/reference/functions/defaultShouldDehydrateMutation.md +++ b/docs/framework/angular/reference/functions/defaultShouldDehydrateMutation.md @@ -7,7 +7,7 @@ title: defaultShouldDehydrateMutation function defaultShouldDehydrateMutation(mutation: Mutation): boolean; ``` -Defined in: [packages/query-core/src/hydration.ts:178](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L178) +Defined in: packages/query-core/dist-ts/src/hydration.d.ts:77 The default `shouldDehydrateMutation` predicate used by `dehydrate`. Only dehydrates mutations that are currently paused (e.g. paused by `networkMode` while offline). diff --git a/docs/framework/angular/reference/functions/defaultShouldDehydrateQuery.md b/docs/framework/angular/reference/functions/defaultShouldDehydrateQuery.md index 736579349d7..35b7cd8d815 100644 --- a/docs/framework/angular/reference/functions/defaultShouldDehydrateQuery.md +++ b/docs/framework/angular/reference/functions/defaultShouldDehydrateQuery.md @@ -7,7 +7,7 @@ title: defaultShouldDehydrateQuery function defaultShouldDehydrateQuery(query: Query): boolean; ``` -Defined in: [packages/query-core/src/hydration.ts:186](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L186) +Defined in: packages/query-core/dist-ts/src/hydration.d.ts:82 The default `shouldDehydrateQuery` predicate used by `dehydrate`. Only dehydrates queries whose status is `'success'`. diff --git a/docs/framework/angular/reference/functions/dehydrate.md b/docs/framework/angular/reference/functions/dehydrate.md index 201200efdfa..ff2ac4eae35 100644 --- a/docs/framework/angular/reference/functions/dehydrate.md +++ b/docs/framework/angular/reference/functions/dehydrate.md @@ -4,10 +4,10 @@ title: dehydrate --- ```ts -function dehydrate(client: QueryClient, options: DehydrateOptions): DehydratedState; +function dehydrate(client: QueryClient, options?: DehydrateOptions): DehydratedState; ``` -Defined in: [packages/query-core/src/hydration.ts:208](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L208) +Defined in: packages/query-core/dist-ts/src/hydration.d.ts:101 Dehydrates a `QueryClient`'s cache (queries and mutations) into a plain, serializable `DehydratedState`, typically to embed in server-rendered markup and later restore into a client-side `QueryClient` via `hydrate`. @@ -21,9 +21,9 @@ falling back to the client's `dehydrate` default options, and finally to `defaul [`QueryClient`](../classes/QueryClient.md) -### options +### options? -[`DehydrateOptions`](../interfaces/DehydrateOptions.md) = `{}` +[`DehydrateOptions`](../interfaces/DehydrateOptions.md) ## Returns diff --git a/docs/framework/angular/reference/functions/dehydrateQuery.md b/docs/framework/angular/reference/functions/dehydrateQuery.md index 0dcd0904691..cb822128162 100644 --- a/docs/framework/angular/reference/functions/dehydrateQuery.md +++ b/docs/framework/angular/reference/functions/dehydrateQuery.md @@ -10,7 +10,7 @@ function dehydrateQuery( shouldRedactErrors?: (error: unknown) => boolean): DehydratedQuery; ``` -Defined in: [packages/query-core/src/hydration.ts:149](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L149) +Defined in: packages/query-core/dist-ts/src/hydration.d.ts:72 Dehydrates a single `Query` into a serializable `DehydratedQuery` snapshot. Note that most query config (e.g. `queryFn`, `staleTime`) is not dehydrated but instead meant to be configured again when consuming the diff --git a/docs/framework/angular/reference/functions/experimental_streamedQuery.md b/docs/framework/angular/reference/functions/experimental_streamedQuery.md index 29a8ae5d889..a361f08f15f 100644 --- a/docs/framework/angular/reference/functions/experimental_streamedQuery.md +++ b/docs/framework/angular/reference/functions/experimental_streamedQuery.md @@ -4,10 +4,10 @@ title: experimental_streamedQuery --- ```ts -function experimental_streamedQuery(streamFn: StreamedQueryParams): (context: object) => TData | Promise; +function experimental_streamedQuery(streamFn: StreamedQueryParams): QueryFunction; ``` -Defined in: [packages/query-core/src/streamedQuery.ts:68](https://github.com/TanStack/query/blob/main/packages/query-core/src/streamedQuery.ts#L68) +Defined in: packages/query-core/dist-ts/src/streamedQuery.d.ts:53 This is a helper function to create a query function that streams data from an AsyncIterable. Data will be an Array of all the chunks received. @@ -38,45 +38,7 @@ The function that returns an AsyncIterable to stream data from. ## Returns -```ts -(context: object): TData | Promise; -``` - -### Parameters - -#### context - -##### client - -[`QueryClient`](../classes/QueryClient.md) - -##### direction? - -`unknown` - -**Deprecated** - -if you want access to the direction, you can add it to the pageParam - -##### meta - -`Record`\<`string`, `unknown`\> \| `undefined` - -##### pageParam? - -`unknown` - -##### queryKey - -`TQueryKey` - -##### signal - -`AbortSignal` - -### Returns - -`TData` \| `Promise`\<`TData`\> +[`QueryFunction`](../type-aliases/QueryFunction.md)\<`TData`, `TQueryKey`\> ## Example diff --git a/docs/framework/angular/reference/functions/hashKey.md b/docs/framework/angular/reference/functions/hashKey.md index 82e2b70512e..08c5c0d2e8d 100644 --- a/docs/framework/angular/reference/functions/hashKey.md +++ b/docs/framework/angular/reference/functions/hashKey.md @@ -7,7 +7,7 @@ title: hashKey function hashKey(queryKey: readonly unknown[]): string; ``` -Defined in: [packages/query-core/src/utils.ts:284](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L284) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:133 Default query & mutation keys hash function. Hashes the value into a stable hash. diff --git a/docs/framework/angular/reference/functions/hydrate.md b/docs/framework/angular/reference/functions/hydrate.md index 435603b3af4..f91d93e1092 100644 --- a/docs/framework/angular/reference/functions/hydrate.md +++ b/docs/framework/angular/reference/functions/hydrate.md @@ -10,7 +10,7 @@ function hydrate( options?: HydrateOptions): void; ``` -Defined in: [packages/query-core/src/hydration.ts:265](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L265) +Defined in: packages/query-core/dist-ts/src/hydration.d.ts:119 Restores a `DehydratedState` (as produced by `dehydrate`) into a `QueryClient`'s cache, typically to seed the client with data already fetched on the server. `mutations` and `queries` are each optional on `dehydratedState`. diff --git a/docs/framework/angular/reference/functions/infiniteQueryOptions.md b/docs/framework/angular/reference/functions/infiniteQueryOptions.md index f1165075bbe..12439949a44 100644 --- a/docs/framework/angular/reference/functions/infiniteQueryOptions.md +++ b/docs/framework/angular/reference/functions/infiniteQueryOptions.md @@ -9,7 +9,7 @@ title: infiniteQueryOptions function infiniteQueryOptions(options: DefinedInitialDataInfiniteOptions): CreateInfiniteQueryOptions & object & QueryKeyWithDataTag, TError>; ``` -Defined in: [packages/angular-query/src/infinite-query-options.ts:87](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L87) +Defined in: [packages/angular-query/src/infinite-query-options.ts:180](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L180) You can generally pass everything to `infiniteQueryOptions` that you can also pass to `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as @@ -51,7 +51,7 @@ The [DefinedInitialDataInfiniteOptions](../type-aliases/DefinedInitialDataInfini ### Returns -[`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `InfiniteData`\<`TQueryFnData`, `unknown`\>, `TError`\> +The same options object, typed so that `queryKey` carries the inferred data type. ### See @@ -65,7 +65,7 @@ automatically as the user scrolls. ### Example ```angular-ts -import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' +import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query' export const projectsOptions = infiniteQueryOptions({ queryKey: ['projects'], @@ -100,7 +100,7 @@ export class Projects { function infiniteQueryOptions(options: UnusedSkipTokenInfiniteOptions): OmitKeyof, "queryFn"> & object & QueryKeyWithDataTag, TError>; ``` -Defined in: [packages/angular-query/src/infinite-query-options.ts:117](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L117) +Defined in: [packages/angular-query/src/infinite-query-options.ts:254](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L254) You can generally pass everything to `infiniteQueryOptions` that you can also pass to `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as @@ -140,7 +140,7 @@ The [UnusedSkipTokenInfiniteOptions](../type-aliases/UnusedSkipTokenInfiniteOpti ### Returns -`OmitKeyof`\<[`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>, `"queryFn"`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `InfiniteData`\<`TQueryFnData`, `unknown`\>, `TError`\> +The same options object, typed so that `queryKey` carries the inferred data type. ### Remarks @@ -151,7 +151,7 @@ automatically as the user scrolls. A parameterized factory, so the same options object can be reused per `postId`: ```angular-ts -import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' +import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query' export const commentsOptions = (postId: string) => infiniteQueryOptions({ @@ -195,7 +195,7 @@ export class Comments { function infiniteQueryOptions(options: UndefinedInitialDataInfiniteOptions): CreateInfiniteQueryOptions & object & QueryKeyWithDataTag, TError>; ``` -Defined in: [packages/angular-query/src/infinite-query-options.ts:147](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L147) +Defined in: [packages/angular-query/src/infinite-query-options.ts:328](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L328) You can generally pass everything to `infiniteQueryOptions` that you can also pass to `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as @@ -235,7 +235,7 @@ The [UndefinedInitialDataInfiniteOptions](../type-aliases/UndefinedInitialDataIn ### Returns -[`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `InfiniteData`\<`TQueryFnData`, `unknown`\>, `TError`\> +The same options object, typed so that `queryKey` carries the inferred data type. ### Remarks @@ -246,7 +246,7 @@ automatically as the user scrolls) and that use `skipToken` to disable the query A parameterized factory, so the same options object can be reused per `postId`: ```angular-ts -import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' +import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query' export const commentsOptions = (postId: string) => infiniteQueryOptions({ diff --git a/docs/framework/angular/reference/functions/injectInfiniteQuery.md b/docs/framework/angular/reference/functions/injectInfiniteQuery.md index def9d593971..c81c036462d 100644 --- a/docs/framework/angular/reference/functions/injectInfiniteQuery.md +++ b/docs/framework/angular/reference/functions/injectInfiniteQuery.md @@ -3,26 +3,16 @@ id: injectInfiniteQuery title: injectInfiniteQuery --- -# Function: injectInfiniteQuery() - -Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key. -Infinite queries can additively "load more" data onto an existing set of data or support infinite scroll. - -## Param - -A function that returns infinite query options. - -## See - -https://tanstack.com/query/latest/docs/framework/angular/guides/infinite-queries - ## Call Signature ```ts -function injectInfiniteQuery(optionsFn): DefinedCreateInfiniteQueryResult; +function injectInfiniteQuery(optionsFn: () => DefinedInitialDataInfiniteOptions): DefinedCreateInfiniteQueryResult; ``` -Defined in: [packages/angular-query/src/inject-infinite-query.ts:27](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-infinite-query.ts#L27) +Defined in: [packages/angular-query/src/inject-infinite-query.ts:39](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-infinite-query.ts#L39) + +This overload is selected when `initialData` is set, so the resulting `data` signal is never `undefined` +(unless a `select` changes `TData` to include `undefined`). ### Type Parameters @@ -52,17 +42,31 @@ Defined in: [packages/angular-query/src/inject-infinite-query.ts:27](https://git () => [`DefinedInitialDataInfiniteOptions`](../type-aliases/DefinedInitialDataInfiniteOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> +A function returning infinite-query options with `initialData` set. Similar to +`computed` from Angular, this function runs in the reactive context. + ### Returns [`DefinedCreateInfiniteQueryResult`](../type-aliases/DefinedCreateInfiniteQueryResult.md)\<`TData`, `TError`\> +The infinite query result, typed so that `data` is never `undefined`. + +### See + + - https://tanstack.com/query/latest/docs/framework/angular/guides/infinite-queries + - [infiniteQueryOptions](infiniteQueryOptions.md) to share these options between `injectInfiniteQuery` and +`queryClient.infiniteQuery`. + ## Call Signature ```ts -function injectInfiniteQuery(optionsFn): CreateInfiniteQueryResult; +function injectInfiniteQuery(optionsFn: () => UndefinedInitialDataInfiniteOptions): CreateInfiniteQueryResult; ``` -Defined in: [packages/angular-query/src/inject-infinite-query.ts:43](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-infinite-query.ts#L43) +Defined in: [packages/angular-query/src/inject-infinite-query.ts:95](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-infinite-query.ts#L95) + +Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key. +Infinite queries can additively "load more" data onto an existing set of data or support infinite scroll. ### Type Parameters @@ -92,17 +96,62 @@ Defined in: [packages/angular-query/src/inject-infinite-query.ts:43](https://git () => [`UndefinedInitialDataInfiniteOptions`](../type-aliases/UndefinedInitialDataInfiniteOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> +A function that returns infinite query options. Similar to `computed` from Angular, +this function runs in the reactive context, so signals read inside it drive the query. + ### Returns [`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\<`TData`, `TError`\> +The infinite query result. + +### See + + - https://tanstack.com/query/latest/docs/framework/angular/guides/infinite-queries + - [infiniteQueryOptions](infiniteQueryOptions.md) to share these options between `injectInfiniteQuery` and +`queryClient.infiniteQuery`. + +### Example + +```angular-ts +@Component({ + selector: 'projects', + template: ` + @if (query.isPending()) { + Loading... + } @else if (query.isError()) { + Error: {{ query.error()?.message }} + } @else { + @for (page of query.data().pages; track $index) { + @for (project of page; track project.id) { +

{{ project.name }}

+ } + } + + } + `, +}) +export class Projects { + readonly query = injectInfiniteQuery(() => ({ + queryKey: ['projects'], + queryFn: ({ pageParam }) => fetchProjects(pageParam), + initialPageParam: 0, + getNextPageParam: (lastPage) => lastPage.nextCursor, + })) +} +``` + ## Call Signature ```ts -function injectInfiniteQuery(optionsFn): CreateInfiniteQueryResult; +function injectInfiniteQuery(optionsFn: () => CreateInfiniteQueryOptions): CreateInfiniteQueryResult; ``` -Defined in: [packages/angular-query/src/inject-infinite-query.ts:59](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-infinite-query.ts#L59) +Defined in: [packages/angular-query/src/inject-infinite-query.ts:121](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-infinite-query.ts#L121) + +This overload accepts the general [CreateInfiniteQueryOptions](../interfaces/CreateInfiniteQueryOptions.md) shape rather than the +`initialData`-aware overloads above, so whether `data` is defined can't be inferred from the call +site — useful when wrapping `injectInfiniteQuery` in your own helper. ### Type Parameters @@ -132,6 +181,15 @@ Defined in: [packages/angular-query/src/inject-infinite-query.ts:59](https://git () => [`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> +A function that returns infinite query options. Similar to `computed` from Angular, +this function runs in the reactive context, so signals read inside it drive the query. + ### Returns [`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\<`TData`, `TError`\> + +The infinite query result. + +### See + +https://tanstack.com/query/latest/docs/framework/angular/guides/infinite-queries diff --git a/docs/framework/angular/reference/functions/injectIsFetching.md b/docs/framework/angular/reference/functions/injectIsFetching.md index 48a8aafe436..52f5fcc90a6 100644 --- a/docs/framework/angular/reference/functions/injectIsFetching.md +++ b/docs/framework/angular/reference/functions/injectIsFetching.md @@ -4,7 +4,7 @@ title: injectIsFetching --- ```ts -function injectIsFetching(filters): Signal; +function injectIsFetching(filters: () => QueryFilters): Signal; ``` Defined in: [packages/angular-query/src/inject-is-fetching.ts:15](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-is-fetching.ts#L15) @@ -12,11 +12,13 @@ Defined in: [packages/angular-query/src/inject-is-fetching.ts:15](https://github Injects a signal that tracks the number of queries that your application is loading or fetching in the background (useful for app-wide loading indicators). +Can be used for app-wide loading indicators + ## Parameters ### filters -() => `QueryFilters` +() => [`QueryFilters`](../interfaces/QueryFilters.md) A reactive factory for the filters. @@ -24,37 +26,4 @@ A reactive factory for the filters. `Signal`\<`number`\> -A `Signal` with the number of queries that your application is currently loading or fetching in -the background. - -## Examples - -```angular-ts -@Component({ - selector: 'posts-fetching-indicator', - template: ` - @if (isFetchingPosts()) { - Refreshing posts... - } - `, -}) -export class PostsFetchingIndicator { - // How many queries matching the posts prefix are fetching? - readonly isFetchingPosts = injectIsFetching({ queryKey: ['posts'] }) -} -``` - -A global loading indicator for any query fetching in the background, not just the ones on screen: -```angular-ts -@Component({ - selector: 'global-loading-indicator', - template: ` - @if (isFetching()) { -
Queries are fetching in the background...
- } - `, -}) -export class GlobalLoadingIndicator { - readonly isFetching = injectIsFetching() -} -``` +signal with number of loading or fetching queries. diff --git a/docs/framework/angular/reference/functions/injectIsMutating.md b/docs/framework/angular/reference/functions/injectIsMutating.md index c674046a97b..8f97eade417 100644 --- a/docs/framework/angular/reference/functions/injectIsMutating.md +++ b/docs/framework/angular/reference/functions/injectIsMutating.md @@ -4,19 +4,21 @@ title: injectIsMutating --- ```ts -function injectIsMutating(filters): Signal; +function injectIsMutating(filters: () => MutationFilters): Signal; ``` -Defined in: [packages/angular-query/src/inject-is-mutating.ts:14](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-is-mutating.ts#L14) +Defined in: [packages/angular-query/src/inject-is-mutating.ts:15](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-is-mutating.ts#L15) Injects a signal that tracks the number of mutations that your application currently has `pending` (useful for app-wide loading indicators). +Can be used for app-wide loading indicators + ## Parameters ### filters -() => `MutationFilters` +() => [`MutationFilters`](../interfaces/MutationFilters.md) A reactive factory for the filters. @@ -24,21 +26,4 @@ A reactive factory for the filters. `Signal`\<`number`\> -A `Signal` with the number of mutations that your application currently has `pending`. - -## Example - -```angular-ts -@Component({ - selector: 'posts-mutating-indicator', - template: ` - @if (isMutatingPosts()) { - Saving posts... - } - `, -}) -export class PostsMutatingIndicator { - // How many mutations matching the posts prefix are in progress? - readonly isMutatingPosts = injectIsMutating({ mutationKey: ['posts'] }) -} -``` +A read-only signal with the number of fetching mutations. diff --git a/docs/framework/angular/reference/functions/injectIsRestoring.md b/docs/framework/angular/reference/functions/injectIsRestoring.md index 627aad15b52..6796ffdf83f 100644 --- a/docs/framework/angular/reference/functions/injectIsRestoring.md +++ b/docs/framework/angular/reference/functions/injectIsRestoring.md @@ -7,13 +7,13 @@ title: injectIsRestoring function injectIsRestoring(): Signal; ``` -Defined in: [packages/angular-query/src/inject-is-restoring.ts:22](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-is-restoring.ts#L22) +Defined in: [packages/angular-query/src/inject-is-restoring.ts:21](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-is-restoring.ts#L21) -Returns a readonly signal that is true while the persistence integration restores cached query data. It is false when no restoration is in progress. +Injects a readonly signal that is true while the persistence integration restores +cached query data. Returns false when no restoration is in progress. ## Returns `Signal`\<`boolean`\> -A readonly `Signal` — `true` while a restore is in progress, `false` otherwise (the -default when no `provideIsRestoring` provider is registered). +The current restoration state. diff --git a/docs/framework/angular/reference/functions/injectMutation.md b/docs/framework/angular/reference/functions/injectMutation.md index a4050838d76..19fdc7c820c 100644 --- a/docs/framework/angular/reference/functions/injectMutation.md +++ b/docs/framework/angular/reference/functions/injectMutation.md @@ -4,13 +4,13 @@ title: injectMutation --- ```ts -function injectMutation(optionsFn): CreateMutationResult; +function injectMutation(optionsFn: () => CreateMutationOptions): CreateMutationResult; ``` -Defined in: [packages/angular-query/src/inject-mutation.ts:28](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-mutation.ts#L28) +Defined in: [packages/angular-query/src/inject-mutation.ts:51](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-mutation.ts#L51) -Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. -`injectMutation` is the function for that. Unlike queries, mutations are not run automatically. +Injects a mutation: an imperative function that can be invoked which typically performs server side effects. +Unlike queries, mutations are not run automatically. ## Type Parameters @@ -36,143 +36,36 @@ Unlike queries, mutations are typically used to create/update/delete data or per () => [`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\> -A function that returns mutation options. Similar to `computed` from Angular, -this function runs in the reactive context, so signals read inside it drive the mutation's options. +A function that returns mutation options. Similar to `computed` from Angular, this +function runs in the reactive context, so signals read inside it drive the mutation. ## Returns [`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\> -The mutation result. Value fields are exposed as a `Signal` — read `data`/`error` by calling them -(e.g. `mutation.data()`) — while function fields (`mutate`, `mutateAsync`, `reset`) are called directly, -unchanged. `isSuccess`/`isError`/`isPending`/`isIdle` are type-guard methods you can call to narrow whether -`data` is defined. - -## Remarks - -`mutate`/`mutateAsync` also accept per-call `onSuccess`/`onError`/`onSettled` callbacks as a -second argument, useful for triggering call-site side effects (e.g. navigation) without coupling them to -the shared mutation definition. Callbacks defined in `injectMutationFn` fire for every mutation; per-call -callbacks fire only for the latest call you've made — `mutateAsync` gives you a promise per call instead, -so you can await `Promise.all`/`Promise.allSettled` over several calls and see each one's outcome. +The mutation result, including `mutate` and `mutateAsync`. ## See -[mutationOptions](mutationOptions.md) to share these options across multiple `injectMutation` call sites, or to look -the mutation up elsewhere via its `mutationKey` (e.g. with `injectMutationState`). + - https://tanstack.com/query/latest/docs/framework/angular/guides/mutations + - [mutationOptions](mutationOptions.md) to share these options between `injectMutation` and `injectMutationState`. -## Examples +## Example ```angular-ts @Component({ - selector: 'todos', template: ` - @if (addMutation.isPending()) { - Adding todo... - } @else if (addMutation.isError()) { -
An error occurred: {{ addMutation.error()?.message }}
+ @if (mutation.isPending()) { + Saving... + } @else if (mutation.isError()) { + Error: {{ mutation.error()?.message }} } - + `, }) -export class Todos { - readonly #queryClient = inject(QueryClient) - - readonly addMutation = injectMutation(() => ({ - mutationFn: addTodo, - onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), +export class CreatePost { + readonly mutation = injectMutation(() => ({ + mutationFn: createPost, })) } ``` - -Optimistic update via `onMutate`, rolling back on `onError`: -```angular-ts -@Component({ - selector: 'todos', - template: ``, -}) -export class Todos { - readonly #queryClient = inject(QueryClient) - - readonly addMutation = injectMutation(() => ({ - mutationFn: addTodo, - onMutate: async (newTodo) => { - await this.#queryClient.cancelQueries({ queryKey: ['todos'] }) - const previousTodos = this.#queryClient.getQueryData>(['todos']) - - this.#queryClient.setQueryData>(['todos'], (old) => [ - ...(old ?? []), - newTodo, - ]) - - // Passed to `onError` as `onMutateResult` if the mutation fails. - return { previousTodos } - }, - onError: (_err, _newTodo, onMutateResult) => { - this.#queryClient.setQueryData(['todos'], onMutateResult?.previousTodos) - }, - onSettled: () => { - this.#queryClient.invalidateQueries({ queryKey: ['todos'] }) - }, - })) -} -``` - -Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a promise per -call instead, so you can wait for all of them when they succeed: -```angular-ts -@Component({ - selector: 'todos', - template: ` - - `, -}) -export class Todos { - readonly #queryClient = inject(QueryClient) - - readonly addMutation = injectMutation(() => ({ - mutationFn: addTodo, - onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), - })) - - async handleAddAll(todos: Array) { - try { - await Promise.all(todos.map((todo) => this.addMutation.mutateAsync(todo))) - } catch (error) { - console.error('Failed to add todos:', error) - } - } -} -``` - -If some of the mutations above can fail independently of the others, and you want to know which ones did — -rather than losing that information the moment the first one rejects — swap `Promise.all` for -`Promise.allSettled`: -```angular-ts -@Component({ - selector: 'todos', - template: ` - - `, -}) -export class Todos { - readonly #queryClient = inject(QueryClient) - - readonly addMutation = injectMutation(() => ({ - mutationFn: addTodo, - onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), - })) - - async handleAddAll(todos: Array) { - const addResults = await Promise.allSettled( - todos.map((todo) => this.addMutation.mutateAsync(todo)), - ) - - addResults.forEach((addResult, index) => { - if (addResult.status === 'rejected') { - console.error(`Failed to add "${todos[index]}":`, addResult.reason) - } - }) - } -} -``` diff --git a/docs/framework/angular/reference/functions/injectMutationState.md b/docs/framework/angular/reference/functions/injectMutationState.md index 2b14f5046e5..ba61d160d78 100644 --- a/docs/framework/angular/reference/functions/injectMutationState.md +++ b/docs/framework/angular/reference/functions/injectMutationState.md @@ -4,13 +4,12 @@ title: injectMutationState --- ```ts -function injectMutationState(options): Signal; +function injectMutationState(options: () => MutationStateOptions): Signal; ``` Defined in: [packages/angular-query/src/inject-mutation-state.ts:55](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-mutation-state.ts#L55) -Injects a signal that gives you access to all mutations in the `MutationCache`. You can pass `filters` -([MutationFilters](../interfaces/MutationFilters.md)) to narrow down your mutations, and `select` to transform the mutation state. +Injects a signal that tracks the state of all mutations. ## Type Parameters @@ -20,7 +19,7 @@ Injects a signal that gives you access to all mutations in the `MutationCache`. ### TMutation -`TMutation` *extends* `Mutation`\<`any`, `any`, `any`, `any`\> = `MutationTypeFromResult`\<`TResult`\> +`TMutation` *extends* [`Mutation`](../classes/Mutation.md)\<`any`, `any`, `any`, `any`\> = `MutationTypeFromResult`\<`TResult`\> ## Parameters @@ -28,59 +27,10 @@ Injects a signal that gives you access to all mutations in the `MutationCache`. () => [`MutationStateOptions`](../type-aliases/MutationStateOptions.md)\<`TResult`, `TMutation`\> -A function returning the `filters` to narrow down matched mutations, and an -optional `select` to transform the mutation state. Similar to `computed` from Angular, this function runs -in the reactive context, so signals read inside it re-narrow the matched mutations. +A function that returns mutation state options. ## Returns `Signal`\<`TResult`[]\> -A `Signal` with an Array of whatever `select` returns for each matching mutation. - -## Examples - -Get all variables of all running mutations: -```angular-ts -@Component({ - selector: 'pending-posts', - template: `{{ pendingVariables().length }} posts saving...`, -}) -export class PendingPosts { - readonly pendingVariables = injectMutationState(() => ({ - filters: { status: 'pending' }, - select: (mutation) => mutation.state.variables, - })) -} -``` - -Get all data for specific mutations via the `mutationKey`: -```angular-ts -const mutationKey = ['posts'] - -@Component({ - selector: 'posts', - template: ` - - `, -}) -export class Posts { - // Some mutation that we want to get the state for - readonly createPostMutation = injectMutation(() => ({ - mutationKey, - mutationFn: createPosts, - })) - - readonly savedPosts = injectMutationState(() => ({ - // this mutation key needs to match the mutation key of the given mutation (see above) - filters: { mutationKey, status: 'success' }, - select: (mutation) => mutation.state.data, - })) - - createPost() { - this.createPostMutation.mutate(['New Post']) - } -} -``` +The signal that tracks the state of all mutations. diff --git a/docs/framework/angular/reference/functions/injectQueries.md b/docs/framework/angular/reference/functions/injectQueries.md index f07d91a2b71..04d075d0f46 100644 --- a/docs/framework/angular/reference/functions/injectQueries.md +++ b/docs/framework/angular/reference/functions/injectQueries.md @@ -4,26 +4,13 @@ title: injectQueries --- ```ts -function injectQueries(optionsFn): Signal; +function injectQueries(optionsFn: () => InjectQueriesOptions): Signal; ``` -Defined in: [packages/angular-query/src/inject-queries.ts:43](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-queries.ts#L43) +Defined in: [packages/angular-query/src/inject-queries.ts:57](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-queries.ts#L57) Injects multiple queries that run in parallel and react to Angular signals. -```ts -class UsersComponent { - readonly users = input.required>() - - readonly userQueries = injectQueries(() => ({ - queries: this.users().map((user) => ({ - queryKey: ['user', user.id], - queryFn: () => fetchUserById(user.id), - })), - })) -} -``` - ## Type Parameters ### T @@ -40,10 +27,40 @@ class UsersComponent { () => [`InjectQueriesOptions`](../interfaces/InjectQueriesOptions.md)\<`T`, `TCombinedResult`\> -A function that returns queries' options. +A function that returns the queries' options. Similar to `computed` from Angular, +this function runs in the reactive context, so signals read inside it drive the queries. ## Returns `Signal`\<`TCombinedResult`\> A signal containing the query results in the same order as the input queries. + +## See + +https://tanstack.com/query/latest/docs/framework/angular/guides/parallel-queries + +## Example + +```angular-ts +@Component({ + selector: 'users', + template: ` + @for (query of userQueries(); track $index) { + @if (query.isSuccess()) { +

{{ query.data().name }}

+ } + } + `, +}) +export class UsersComponent { + readonly users = input.required>() + + readonly userQueries = injectQueries(() => ({ + queries: this.users().map((user) => ({ + queryKey: ['user', user.id], + queryFn: () => fetchUserById(user.id), + })), + })) +} +``` diff --git a/docs/framework/angular/reference/functions/injectQuery.md b/docs/framework/angular/reference/functions/injectQuery.md index 860e5ddc567..a26c46d8157 100644 --- a/docs/framework/angular/reference/functions/injectQuery.md +++ b/docs/framework/angular/reference/functions/injectQuery.md @@ -3,58 +3,16 @@ id: injectQuery title: injectQuery --- -# Function: injectQuery() - -Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. - -**Basic example** -```ts -import { lastValueFrom } from 'rxjs' - -class ServiceOrComponent { - query = injectQuery(() => ({ - queryKey: ['repoData'], - queryFn: () => - lastValueFrom( - this.#http.get('https://api.github.com/repos/tanstack/query'), - ), - })) -} -``` - -Similar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context. -In the example below, the query will be automatically enabled and executed when the filter signal changes -to a truthy value. When the filter signal changes back to a falsy value, the query will be disabled. - -**Reactive example** -```ts -class ServiceOrComponent { - filter = signal('') - - todosQuery = injectQuery(() => ({ - queryKey: ['todos', this.filter()], - queryFn: () => fetchTodos(this.filter()), - // Signals can be combined with expressions - enabled: !!this.filter(), - })) -} -``` - -## Param - -A function that returns query options. - -## See - -https://tanstack.com/query/latest/docs/framework/angular/guides/queries - ## Call Signature ```ts -function injectQuery(optionsFn): DefinedCreateQueryResult; +function injectQuery(optionsFn: () => DefinedInitialDataOptions): DefinedCreateQueryResult; ``` -Defined in: [packages/angular-query/src/inject-query.ts:17](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-query.ts#L17) +Defined in: [packages/angular-query/src/inject-query.ts:61](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-query.ts#L61) + +This overload is selected when `initialData` is set on the options returned by `optionsFn`, so the +resulting `data` signal is never `undefined` (unless a `select` changes `TData` to include `undefined`). ### Type Parameters @@ -80,17 +38,59 @@ Defined in: [packages/angular-query/src/inject-query.ts:17](https://github.com/T () => [`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> +A function returning the [DefinedInitialDataOptions](../type-aliases/DefinedInitialDataOptions.md) to use — everything you +can pass to `injectQuery`, with `initialData` set. Similar to `computed` from Angular, this function runs +in the reactive context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive the query. + ### Returns [`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<`TData`, `TError`\> +The query result, typed so that `data` is never `undefined` (unless a `select` changes `TData` to +include `undefined`). + +### See + + - https://tanstack.com/query/latest/docs/framework/angular/guides/queries + - [queryOptions](queryOptions.md) to share these options between `injectQuery` and imperative APIs like +`queryClient.query`. + +### Example + +```angular-ts +@Component({ + selector: 'posts', + template: ` + + @if (postsQuery.isError()) { + Error: {{ postsQuery.error()?.message }} + } +
    + @for (post of postsQuery.data(); track post.id) { +
  • {{ post.title }}
  • + } +
+ `, +}) +export class Posts { + readonly postsQuery = injectQuery(() => ({ + queryKey: ['posts'], + queryFn: fetchPosts, + initialData: [], + })) +} +``` + ## Call Signature ```ts -function injectQuery(optionsFn): CreateQueryResult; +function injectQuery(optionsFn: () => UndefinedInitialDataOptions): CreateQueryResult; ``` -Defined in: [packages/angular-query/src/inject-query.ts:31](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-query.ts#L31) +Defined in: [packages/angular-query/src/inject-query.ts:147](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-query.ts#L147) + +Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. ### Type Parameters @@ -116,17 +116,94 @@ Defined in: [packages/angular-query/src/inject-query.ts:31](https://github.com/T () => [`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> +A function returning the [UndefinedInitialDataOptions](../type-aliases/UndefinedInitialDataOptions.md) to use — everything +you can pass to `injectQuery`. Similar to `computed` from Angular, this function runs in the reactive +context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive the query. + ### Returns [`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<`TData`, `TError`\> +The query result. `status()` is `'pending'` if there is no cached data to display, `'error'` if +the last fetch attempt failed, or `'success'` if the query has data to display. `isPending`/`isSuccess`/ +`isError` are type-guard methods for convenience. + +### See + + - https://tanstack.com/query/latest/docs/framework/angular/guides/queries + - [queryOptions](queryOptions.md) to share these options between `injectQuery` and imperative APIs like +`queryClient.query`. + +### Examples + +```angular-ts +@Component({ + selector: 'posts', + template: ` + @if (postsQuery.isPending()) { + Loading... + } @else if (postsQuery.isError()) { + Error: {{ postsQuery.error()?.message }} + } @else { +
    + @for (post of postsQuery.data(); track post.id) { +
  • {{ post.title }}
  • + } +
+ } + `, +}) +export class Posts { + readonly postsQuery = injectQuery(() => ({ + queryKey: ['posts'], + queryFn: fetchPosts, + })) +} +``` + +Similar to `computed` from Angular, the function passed to `injectQuery` runs in the reactive context. In +the example below, the query is automatically enabled and executed when the filter signal changes to a +truthy value. When the filter signal changes back to a falsy value, the query is disabled. +```angular-ts +@Component({ + selector: 'posts', + template: ` + + @if (postsQuery.isPending()) { + Loading... + } @else if (postsQuery.isError()) { + Error: {{ postsQuery.error()?.message }} + } @else { +
    + @for (post of postsQuery.data(); track post.id) { +
  • {{ post.title }}
  • + } +
+ } + `, +}) +export class Posts { + readonly filter = signal('') + + readonly postsQuery = injectQuery(() => ({ + queryKey: ['posts', this.filter()], + queryFn: () => fetchPosts(this.filter()), + enabled: !!this.filter(), + })) +} +``` + ## Call Signature ```ts -function injectQuery(optionsFn): CreateQueryResult; +function injectQuery(optionsFn: () => CreateQueryOptions): CreateQueryResult; ``` -Defined in: [packages/angular-query/src/inject-query.ts:45](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-query.ts#L45) +Defined in: [packages/angular-query/src/inject-query.ts:171](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-query.ts#L171) + +This overload accepts the general [CreateQueryOptions](../type-aliases/CreateQueryOptions.md) shape rather than the `initialData`-aware +overloads above, so whether `data` is defined can't be inferred from the call site — useful when wrapping +`injectQuery` in your own helper function that forwards caller-provided options. ### Type Parameters @@ -152,6 +229,15 @@ Defined in: [packages/angular-query/src/inject-query.ts:45](https://github.com/T () => [`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> +A function that returns query options. Similar to `computed` from Angular, this +function runs in the reactive context, so signals read inside it drive the query. + ### Returns [`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<`TData`, `TError`\> + +The query result. + +### See + +https://tanstack.com/query/latest/docs/framework/angular/guides/queries diff --git a/docs/framework/angular/reference/functions/isCancelledError.md b/docs/framework/angular/reference/functions/isCancelledError.md index c89686d2851..d07b38afc01 100644 --- a/docs/framework/angular/reference/functions/isCancelledError.md +++ b/docs/framework/angular/reference/functions/isCancelledError.md @@ -7,7 +7,7 @@ title: isCancelledError function isCancelledError(value: any): value is CancelledError; ``` -Defined in: [packages/query-core/src/retryer.ts:94](https://github.com/TanStack/query/blob/main/packages/query-core/src/retryer.ts#L94) +Defined in: packages/query-core/dist-ts/src/retryer.d.ts:55 ## Parameters diff --git a/docs/framework/angular/reference/functions/keepPreviousData.md b/docs/framework/angular/reference/functions/keepPreviousData.md index 930de5e2078..70fb817f096 100644 --- a/docs/framework/angular/reference/functions/keepPreviousData.md +++ b/docs/framework/angular/reference/functions/keepPreviousData.md @@ -7,7 +7,7 @@ title: keepPreviousData function keepPreviousData(previousData: T | undefined): T | undefined; ``` -Defined in: [packages/query-core/src/utils.ts:499](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L499) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:166 Intended to be passed as a query's `placeholderData` option, for example `placeholderData: keepPreviousData`. Instead of resetting the query's data to `undefined` while a new diff --git a/docs/framework/angular/reference/functions/matchMutation.md b/docs/framework/angular/reference/functions/matchMutation.md index 0bc16b361f7..5ce8079287b 100644 --- a/docs/framework/angular/reference/functions/matchMutation.md +++ b/docs/framework/angular/reference/functions/matchMutation.md @@ -7,7 +7,7 @@ title: matchMutation function matchMutation(filters: MutationFilters, mutation: Mutation): boolean; ``` -Defined in: [packages/query-core/src/utils.ts:237](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L237) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:121 Checks whether a mutation matches the given [MutationFilters](../interfaces/MutationFilters.md). Every filter that is specified must match; filters that are left unspecified are ignored. diff --git a/docs/framework/angular/reference/functions/matchQuery.md b/docs/framework/angular/reference/functions/matchQuery.md index ce575fc2b69..519a5821f3e 100644 --- a/docs/framework/angular/reference/functions/matchQuery.md +++ b/docs/framework/angular/reference/functions/matchQuery.md @@ -7,7 +7,7 @@ title: matchQuery function matchQuery(filters: QueryFilters, query: Query): boolean; ``` -Defined in: [packages/query-core/src/utils.ts:175](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L175) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:106 Checks whether a query matches the given [QueryFilters](../interfaces/QueryFilters.md). Every filter that is specified must match; filters that are left unspecified are ignored. diff --git a/docs/framework/angular/reference/functions/mutationOptions.md b/docs/framework/angular/reference/functions/mutationOptions.md index 813132819b0..6461514941b 100644 --- a/docs/framework/angular/reference/functions/mutationOptions.md +++ b/docs/framework/angular/reference/functions/mutationOptions.md @@ -9,7 +9,7 @@ title: mutationOptions function mutationOptions(options: WithRequired, "mutationKey">): WithRequired, "mutationKey">; ``` -Defined in: [packages/angular-query/src/mutation-options.ts:39](https://github.com/TanStack/query/blob/main/packages/angular-query/src/mutation-options.ts#L39) +Defined in: [packages/angular-query/src/mutation-options.ts:40](https://github.com/TanStack/query/blob/main/packages/angular-query/src/mutation-options.ts#L40) You can generally pass everything to `mutationOptions` that you can also pass to `injectMutation`. A `mutationKey` is required on this overload so the mutation can be looked up later, e.g. with @@ -56,7 +56,7 @@ The same options object, unchanged. Looking the mutation up elsewhere via its `mutationKey`, e.g. for a global "saving…" indicator: ```angular-ts -import { mutationOptions, injectMutationState } from '@tanstack/angular-query-experimental' +import { mutationOptions, injectMutationState } from '@tanstack/angular-query' const createPostOptions = mutationOptions({ mutationKey: ['posts', 'create'], @@ -85,7 +85,7 @@ export class SavingIndicator { function mutationOptions(options: Omit, "mutationKey">): Omit, "mutationKey">; ``` -Defined in: [packages/angular-query/src/mutation-options.ts:53](https://github.com/TanStack/query/blob/main/packages/angular-query/src/mutation-options.ts#L53) +Defined in: [packages/angular-query/src/mutation-options.ts:98](https://github.com/TanStack/query/blob/main/packages/angular-query/src/mutation-options.ts#L98) You can generally pass everything to `mutationOptions` that you can also pass to `injectMutation`. No `mutationKey` is required on this overload — use this when you don't need to target the mutation via a @@ -137,7 +137,7 @@ See the other overload's example for looking a mutation up via `injectMutationSt Sharing options across services, so `QueriesService` stays the single place a mutation is defined: ```angular-ts -import { mutationOptions, injectMutation } from '@tanstack/angular-query-experimental' +import { mutationOptions, injectMutation } from '@tanstack/angular-query' @Injectable({ providedIn: 'root' }) export class QueriesService { diff --git a/docs/framework/angular/reference/functions/noop.md b/docs/framework/angular/reference/functions/noop.md index 01fb409f4e9..df6f503cf26 100644 --- a/docs/framework/angular/reference/functions/noop.md +++ b/docs/framework/angular/reference/functions/noop.md @@ -9,7 +9,7 @@ title: noop function noop(): void; ``` -Defined in: [packages/query-core/src/utils.ts:119](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L119) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:87 A function that does nothing. @@ -23,7 +23,7 @@ A function that does nothing. function noop(): undefined; ``` -Defined in: [packages/query-core/src/utils.ts:120](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L120) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:88 A function that does nothing. diff --git a/docs/framework/angular/reference/functions/partialMatchKey.md b/docs/framework/angular/reference/functions/partialMatchKey.md index a0de7df1fe2..09cf8af5e54 100644 --- a/docs/framework/angular/reference/functions/partialMatchKey.md +++ b/docs/framework/angular/reference/functions/partialMatchKey.md @@ -7,7 +7,7 @@ title: partialMatchKey function partialMatchKey(a: readonly unknown[], b: readonly unknown[]): boolean; ``` -Defined in: [packages/query-core/src/utils.ts:300](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L300) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:137 Checks if key `b` partially matches with key `a`. diff --git a/docs/framework/angular/reference/functions/provideTanStackQuery.md b/docs/framework/angular/reference/functions/provideTanStackQuery.md index e50e8e9f560..e2577acb710 100644 --- a/docs/framework/angular/reference/functions/provideTanStackQuery.md +++ b/docs/framework/angular/reference/functions/provideTanStackQuery.md @@ -4,10 +4,10 @@ title: provideTanStackQuery --- ```ts -function provideTanStackQuery(queryClientFactory, ...features): EnvironmentProviders; +function provideTanStackQuery(queryClientFactory: () => QueryClient, ...features: readonly QueryFeature[]): EnvironmentProviders; ``` -Defined in: [packages/angular-query/src/providers.ts:99](https://github.com/TanStack/query/blob/main/packages/angular-query/src/providers.ts#L99) +Defined in: [packages/angular-query/src/providers.ts:102](https://github.com/TanStack/query/blob/main/packages/angular-query/src/providers.ts#L102) Provides a `QueryClient` and optional TanStack Query features. The factory runs once per injector in Angular's injection context, so it can @@ -15,6 +15,28 @@ call `inject()` and each SSR request can receive an independent cache. **Example - standalone** +## Parameters + +### queryClientFactory + +() => [`QueryClient`](../classes/QueryClient.md) + +Creates or resolves a `QueryClient` in the injection context. + +### features + +...readonly [`QueryFeature`](../interfaces/QueryFeature.md)[] + +Optional features to configure additional Query functionality. + +## Returns + +`EnvironmentProviders` + +A single EnvironmentProviders value (do not spread into `providers`). + +## Example + ```ts import { provideTanStackQuery, @@ -40,36 +62,6 @@ bootstrapApplication(AppComponent, { }) ``` -Resolve an existing token inside the factory when another provider owns client creation: - -```ts -export const MY_QUERY_CLIENT = new InjectionToken('', { - factory: () => new QueryClient(), -}) - -providers: [provideTanStackQuery(() => inject(MY_QUERY_CLIENT))] -``` - -## Parameters - -### queryClientFactory - -Creates or resolves a `QueryClient` in the injection context. - -() => `QueryClient` - -### features - -...readonly [`QueryFeature`](../interfaces/QueryFeature.md)[] - -Optional features to configure additional Query functionality. - -## Returns - -`EnvironmentProviders` - -A single EnvironmentProviders value (do not spread into `providers`). - ## See - https://tanstack.com/query/v5/docs/framework/angular/quick-start diff --git a/docs/framework/angular/reference/functions/queryOptions.md b/docs/framework/angular/reference/functions/queryOptions.md index e0902b6aa41..b647e507bd6 100644 --- a/docs/framework/angular/reference/functions/queryOptions.md +++ b/docs/framework/angular/reference/functions/queryOptions.md @@ -3,35 +3,20 @@ id: queryOptions title: queryOptions --- -Allows sharing and re-using query options in a type-safe way. - -The `queryKey` will be tagged with the type from `queryFn`. - -**Example** +## Call Signature ```ts - const { queryKey } = queryOptions({ - queryKey: ['key'], - queryFn: () => Promise.resolve(5), - // ^? Promise - }) - - const queryClient = new QueryClient() - const data = queryClient.getQueryData(queryKey) - // ^? number | undefined +function queryOptions(options: DefinedInitialDataOptions): CreateQueryOptions & object & QueryKeyWithDataTag; ``` -## Param +Defined in: [packages/angular-query/src/query-options.ts:134](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L134) -The query options to tag with the type from `queryFn`. - -## Call Signature - -```ts -function queryOptions(options): CreateQueryOptions & object & QueryKeyWithDataTag; -``` +You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options +can be shared across functions and imperative APIs such as `queryClient.query`. `options.queryKey` is +required and is the query key to generate options for. -Defined in: [packages/angular-query/src/query-options.ts:50](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L50) +This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless +a `select` changes `TData` to include `undefined`). ### Type Parameters @@ -57,9 +42,50 @@ Defined in: [packages/angular-query/src/query-options.ts:50](https://github.com/ [`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> +The [DefinedInitialDataOptions](../type-aliases/DefinedInitialDataOptions.md) to use — everything you can pass to `injectQuery`, +with `initialData` set. + ### Returns -[`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `TQueryFnData`, `TError`\> +[`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> & `object` & [`QueryKeyWithDataTag`](../type-aliases/QueryKeyWithDataTag.md)\<`TQueryKey`, `TQueryFnData`, `TError`\> + +The same options object, typed so that `queryKey` carries the inferred data type. + +### See + + - [injectQuery](injectQuery.md) to run a query with these options. + - [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. + +### Example + +```angular-ts +import { queryOptions, injectQuery } from '@tanstack/angular-query' + +export const postsOptions = queryOptions({ + queryKey: ['posts'], + queryFn: fetchPosts, + initialData: [], +}) + +@Component({ + selector: 'posts', + template: ` + + @if (postsQuery.isError()) { + Error: {{ postsQuery.error()?.message }} + } +
    + @for (post of postsQuery.data(); track post.id) { +
  • {{ post.title }}
  • + } +
+ `, +}) +export class Posts { + readonly postsQuery = injectQuery(() => postsOptions) +} +``` ## Call Signature @@ -67,7 +93,11 @@ Defined in: [packages/angular-query/src/query-options.ts:50](https://github.com/ function queryOptions(options: UnusedSkipTokenOptions): OmitKeyof, "queryFn"> & object & QueryKeyWithDataTag; ``` -Defined in: [packages/angular-query/src/query-options.ts:60](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L60) +Defined in: [packages/angular-query/src/query-options.ts:183](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L183) + +You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options +can be shared across functions and imperative APIs such as `queryClient.query`. `options.queryKey` is +required and is the query key to generate options for. ### Type Parameters @@ -93,9 +123,46 @@ Defined in: [packages/angular-query/src/query-options.ts:60](https://github.com/ [`UnusedSkipTokenOptions`](../type-aliases/UnusedSkipTokenOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> +The [UnusedSkipTokenOptions](../type-aliases/UnusedSkipTokenOptions.md) to use — everything you can pass to `injectQuery`. + ### Returns -`OmitKeyof`\<[`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>, `"queryFn"`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `TQueryFnData`, `TError`\> +The same options object, typed so that `queryKey` carries the inferred data type. + +### See + + - [injectQuery](injectQuery.md) to run a query with these options. + - [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. + +### Example + +A parameterized factory, so the same options object can be reused per `id`: +```angular-ts +import { queryOptions, injectQuery } from '@tanstack/angular-query' + +export const postOptions = (id: string) => + queryOptions({ + queryKey: ['post', id], + queryFn: () => fetchPost(id), + }) + +@Component({ + selector: 'post', + template: ` + @if (postQuery.isPending()) { + Loading... + } @else if (postQuery.isError()) { + Error: {{ postQuery.error()?.message }} + } @else { +

{{ postQuery.data().title }}

+ } + `, +}) +export class Post { + readonly id = signal('1') + readonly postQuery = injectQuery(() => postOptions(this.id())) +} +``` ## Call Signature @@ -103,7 +170,11 @@ Defined in: [packages/angular-query/src/query-options.ts:60](https://github.com/ function queryOptions(options: UndefinedInitialDataOptions): CreateQueryOptions & object & QueryKeyWithDataTag; ``` -Defined in: [packages/angular-query/src/query-options.ts:70](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L70) +Defined in: [packages/angular-query/src/query-options.ts:264](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L264) + +You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options +can be shared across functions and imperative APIs such as `queryClient.query`. `options.queryKey` is +required and is the query key to generate options for. ### Type Parameters @@ -129,6 +200,77 @@ Defined in: [packages/angular-query/src/query-options.ts:70](https://github.com/ [`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> +The [UndefinedInitialDataOptions](../type-aliases/UndefinedInitialDataOptions.md) to use — everything you can pass to `injectQuery`. + ### Returns -[`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> & `object` & `QueryKeyWithDataTag`\<`TQueryKey`, `TQueryFnData`, `TError`\> +The same options object, typed so that `queryKey` carries the inferred data type. + +### See + + - [injectQuery](injectQuery.md) to run a query with these options. + - [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. + +### Remarks + +This is the only overload that accepts `queryFn: skipToken`, shown below. + +### Examples + +A parameterized factory, so the same options object can be reused per `id`: +```angular-ts +import { queryOptions, injectQuery } from '@tanstack/angular-query' + +export const postOptions = (id: string) => + queryOptions({ + queryKey: ['post', id], + queryFn: () => fetchPost(id), + }) + +@Component({ + selector: 'post', + template: ` + @if (postQuery.isPending()) { + Loading... + } @else if (postQuery.isError()) { + Error: {{ postQuery.error()?.message }} + } @else { +

{{ postQuery.data().title }}

+ } + `, +}) +export class Post { + readonly id = signal('1') + readonly postQuery = injectQuery(() => postOptions(this.id())) +} +``` + +A factory that disables the query, type safe, until `postId` is set: +```angular-ts +import { queryOptions, skipToken, injectQuery } from '@tanstack/angular-query' + +export const postOptions = (postId: number | undefined) => + queryOptions({ + queryKey: ['post', postId], + queryFn: postId != null ? () => fetchPost(postId) : skipToken, + }) + +@Component({ + selector: 'post', + template: ` + @if (postId() == null) { + Select a post + } @else if (postQuery.isPending()) { + Loading... + } @else if (postQuery.isError()) { + Error: {{ postQuery.error()?.message }} + } @else { +

{{ postQuery.data().title }}

+ } + `, +}) +export class Post { + readonly postId = signal(undefined) + readonly postQuery = injectQuery(() => postOptions(this.postId())) +} +``` diff --git a/docs/framework/angular/reference/functions/replaceEqualDeep.md b/docs/framework/angular/reference/functions/replaceEqualDeep.md index ae85da0d1c5..ff64d53bf1d 100644 --- a/docs/framework/angular/reference/functions/replaceEqualDeep.md +++ b/docs/framework/angular/reference/functions/replaceEqualDeep.md @@ -10,7 +10,7 @@ function replaceEqualDeep( depth?: number): T; ``` -Defined in: [packages/query-core/src/utils.ts:340](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L340) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:143 This function returns `a` if `b` is deeply equal. If not, it will replace any deeply equal children of `b` with those of `a`. diff --git a/docs/framework/angular/reference/functions/shouldThrowError.md b/docs/framework/angular/reference/functions/shouldThrowError.md index 3ebed7be214..0694941125f 100644 --- a/docs/framework/angular/reference/functions/shouldThrowError.md +++ b/docs/framework/angular/reference/functions/shouldThrowError.md @@ -7,7 +7,7 @@ title: shouldThrowError function shouldThrowError(throwOnError: boolean | T | undefined, params: Parameters): boolean; ``` -Defined in: [packages/query-core/src/utils.ts:582](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L582) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:206 Resolves a `throwOnError` option to a boolean. If `throwOnError` is a function, it is called with `params` (e.g. the error and, depending on the caller, diff --git a/docs/framework/angular/reference/functions/toResource.md b/docs/framework/angular/reference/functions/toResource.md index 3baecfef1dd..76f0a9beeef 100644 --- a/docs/framework/angular/reference/functions/toResource.md +++ b/docs/framework/angular/reference/functions/toResource.md @@ -4,7 +4,7 @@ title: toResource --- ```ts -function toResource(query): QueryResource; +function toResource(query: QueryResourceSource): QueryResource; ``` Defined in: [packages/angular-query/src/query-resource.ts:40](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-resource.ts#L40) diff --git a/docs/framework/angular/reference/functions/withHydrationKey.md b/docs/framework/angular/reference/functions/withHydrationKey.md index 800b9158ac7..a3dae113d8a 100644 --- a/docs/framework/angular/reference/functions/withHydrationKey.md +++ b/docs/framework/angular/reference/functions/withHydrationKey.md @@ -4,10 +4,10 @@ title: withHydrationKey --- ```ts -function withHydrationKey(key): QueryFeature; +function withHydrationKey(key: string): QueryFeature; ``` -Defined in: [packages/angular-query/src/providers.ts:167](https://github.com/TanStack/query/blob/main/packages/angular-query/src/providers.ts#L167) +Defined in: [packages/angular-query/src/providers.ts:169](https://github.com/TanStack/query/blob/main/packages/angular-query/src/providers.ts#L169) Sets a non-default serialization key for this injector's `QueryClient` cache (server dehydrate / browser hydrate via `TransferState`). Use this when you have multiple `QueryClient` instances diff --git a/docs/framework/angular/reference/functions/withNoQueryHydration.md b/docs/framework/angular/reference/functions/withNoQueryHydration.md index b0f003789b4..872d94e6602 100644 --- a/docs/framework/angular/reference/functions/withNoQueryHydration.md +++ b/docs/framework/angular/reference/functions/withNoQueryHydration.md @@ -7,7 +7,7 @@ title: withNoQueryHydration function withNoQueryHydration(): QueryFeature; ``` -Defined in: [packages/angular-query/src/providers.ts:181](https://github.com/TanStack/query/blob/main/packages/angular-query/src/providers.ts#L181) +Defined in: [packages/angular-query/src/providers.ts:183](https://github.com/TanStack/query/blob/main/packages/angular-query/src/providers.ts#L183) Disables `TransferState` hydration and dehydration for the current environment injector. diff --git a/docs/framework/angular/reference/index.md b/docs/framework/angular/reference/index.md index 9b511013b2c..e3437c9a437 100644 --- a/docs/framework/angular/reference/index.md +++ b/docs/framework/angular/reference/index.md @@ -3,21 +3,93 @@ id: "@tanstack/angular-query" title: "@tanstack/angular-query" --- +## Classes + +- [CancelledError](classes/CancelledError.md) +- [InfiniteQueryObserver](classes/InfiniteQueryObserver.md) +- [Mutation](classes/Mutation.md) +- [MutationCache](classes/MutationCache.md) +- [MutationObserver](classes/MutationObserver.md) +- [QueriesObserver](classes/QueriesObserver.md) +- [Query](classes/Query.md) +- [QueryCache](classes/QueryCache.md) +- [QueryClient](classes/QueryClient.md) +- [QueryObserver](classes/QueryObserver.md) + ## Interfaces - [BaseInfiniteQueryNarrowing](interfaces/BaseInfiniteQueryNarrowing.md) - [BaseMutationNarrowing](interfaces/BaseMutationNarrowing.md) - [BaseQueryNarrowing](interfaces/BaseQueryNarrowing.md) +- [CancelOptions](interfaces/CancelOptions.md) - [CreateInfiniteQueryOptions](interfaces/CreateInfiniteQueryOptions.md) - [CreateMutationOptions](interfaces/CreateMutationOptions.md) +- [DefaultOptions](interfaces/DefaultOptions.md) - [DefinedInfiniteQueryNarrowing](interfaces/DefinedInfiniteQueryNarrowing.md) - [DefinedQueryNarrowing](interfaces/DefinedQueryNarrowing.md) +- [DehydratedState](interfaces/DehydratedState.md) +- [DehydrateOptions](interfaces/DehydrateOptions.md) +- [~~EnsureQueryDataOptions~~](interfaces/EnsureQueryDataOptions.md) +- [FetchNextPageOptions](interfaces/FetchNextPageOptions.md) +- [FetchPreviousPageOptions](interfaces/FetchPreviousPageOptions.md) +- [~~FetchQueryOptions~~](interfaces/FetchQueryOptions.md) +- [FocusManager](interfaces/FocusManager.md) +- [HydrateOptions](interfaces/HydrateOptions.md) +- [InfiniteData](interfaces/InfiniteData.md) +- [InfiniteQueryObserverBaseResult](interfaces/InfiniteQueryObserverBaseResult.md) +- [InfiniteQueryObserverLoadingErrorResult](interfaces/InfiniteQueryObserverLoadingErrorResult.md) +- [InfiniteQueryObserverLoadingResult](interfaces/InfiniteQueryObserverLoadingResult.md) +- [InfiniteQueryObserverOptions](interfaces/InfiniteQueryObserverOptions.md) +- [InfiniteQueryObserverPendingResult](interfaces/InfiniteQueryObserverPendingResult.md) +- [InfiniteQueryObserverPlaceholderResult](interfaces/InfiniteQueryObserverPlaceholderResult.md) +- [InfiniteQueryObserverRefetchErrorResult](interfaces/InfiniteQueryObserverRefetchErrorResult.md) +- [InfiniteQueryObserverSuccessResult](interfaces/InfiniteQueryObserverSuccessResult.md) +- [InfiniteQueryPageParamsOptions](interfaces/InfiniteQueryPageParamsOptions.md) +- [InitialPageParam](interfaces/InitialPageParam.md) - [InjectQueriesOptions](interfaces/InjectQueriesOptions.md) +- [InvalidateOptions](interfaces/InvalidateOptions.md) +- [InvalidateQueryFilters](interfaces/InvalidateQueryFilters.md) +- [MutateOptions](interfaces/MutateOptions.md) +- [MutationCacheConfig](interfaces/MutationCacheConfig.md) +- [MutationFilters](interfaces/MutationFilters.md) +- [MutationObserverBaseResult](interfaces/MutationObserverBaseResult.md) +- [MutationObserverErrorResult](interfaces/MutationObserverErrorResult.md) +- [MutationObserverIdleResult](interfaces/MutationObserverIdleResult.md) +- [MutationObserverLoadingResult](interfaces/MutationObserverLoadingResult.md) +- [MutationObserverOptions](interfaces/MutationObserverOptions.md) +- [MutationObserverSuccessResult](interfaces/MutationObserverSuccessResult.md) +- [MutationOptions](interfaces/MutationOptions.md) +- [MutationState](interfaces/MutationState.md) +- [NotifyEvent](interfaces/NotifyEvent.md) +- [OnlineManager](interfaces/OnlineManager.md) +- [QueriesObserverOptions](interfaces/QueriesObserverOptions.md) +- [QueryCacheConfig](interfaces/QueryCacheConfig.md) +- [QueryClientConfig](interfaces/QueryClientConfig.md) +- [QueryExecuteOptions](interfaces/QueryExecuteOptions.md) - [QueryFeature](interfaces/QueryFeature.md) +- [QueryFilters](interfaces/QueryFilters.md) +- [QueryObserverBaseResult](interfaces/QueryObserverBaseResult.md) +- [QueryObserverLoadingErrorResult](interfaces/QueryObserverLoadingErrorResult.md) +- [QueryObserverLoadingResult](interfaces/QueryObserverLoadingResult.md) +- [QueryObserverOptions](interfaces/QueryObserverOptions.md) +- [QueryObserverPendingResult](interfaces/QueryObserverPendingResult.md) +- [QueryObserverPlaceholderResult](interfaces/QueryObserverPlaceholderResult.md) +- [QueryObserverRefetchErrorResult](interfaces/QueryObserverRefetchErrorResult.md) +- [QueryObserverSuccessResult](interfaces/QueryObserverSuccessResult.md) +- [QueryOptions](interfaces/QueryOptions.md) - [QueryResource](interfaces/QueryResource.md) +- [QueryState](interfaces/QueryState.md) +- [RefetchOptions](interfaces/RefetchOptions.md) +- [RefetchQueryFilters](interfaces/RefetchQueryFilters.md) +- [Register](interfaces/Register.md) +- [ResetOptions](interfaces/ResetOptions.md) +- [ResultOptions](interfaces/ResultOptions.md) +- [SetDataOptions](interfaces/SetDataOptions.md) +- [TimeoutManager](interfaces/TimeoutManager.md) ## Type Aliases +- [AnyDataTag](type-aliases/AnyDataTag.md) - [CreateBaseMutationResult](type-aliases/CreateBaseMutationResult.md) - [CreateBaseQueryResult](type-aliases/CreateBaseQueryResult.md) - [CreateInfiniteQueryResult](type-aliases/CreateInfiniteQueryResult.md) @@ -37,10 +109,57 @@ title: "@tanstack/angular-query" - [DefinedInfiniteQueryObserverResult](type-aliases/DefinedInfiniteQueryObserverResult.md) - [DefinedInitialDataInfiniteOptions](type-aliases/DefinedInitialDataInfiniteOptions.md) - [DefinedInitialDataOptions](type-aliases/DefinedInitialDataOptions.md) +- [DefinedQueryObserverResult](type-aliases/DefinedQueryObserverResult.md) +- [DistributiveOmit](type-aliases/DistributiveOmit.md) +- [~~EnsureInfiniteQueryDataOptions~~](type-aliases/EnsureInfiniteQueryDataOptions.md) +- [~~FetchInfiniteQueryOptions~~](type-aliases/FetchInfiniteQueryOptions.md) +- [FetchStatus](type-aliases/FetchStatus.md) +- [GetNextPageParamFunction](type-aliases/GetNextPageParamFunction.md) +- [GetPreviousPageParamFunction](type-aliases/GetPreviousPageParamFunction.md) +- [InferDataFromTag](type-aliases/InferDataFromTag.md) +- [InferErrorFromTag](type-aliases/InferErrorFromTag.md) +- [InfiniteQueryExecuteOptions](type-aliases/InfiniteQueryExecuteOptions.md) +- [InfiniteQueryObserverResult](type-aliases/InfiniteQueryObserverResult.md) +- [InitialDataFunction](type-aliases/InitialDataFunction.md) +- [ManagedTimerId](type-aliases/ManagedTimerId.md) +- [MutateFunction](type-aliases/MutateFunction.md) +- [MutateFunctionRest](type-aliases/MutateFunctionRest.md) +- [MutationCacheNotifyEvent](type-aliases/MutationCacheNotifyEvent.md) +- [MutationFunction](type-aliases/MutationFunction.md) +- [MutationFunctionContext](type-aliases/MutationFunctionContext.md) +- [MutationKey](type-aliases/MutationKey.md) +- [MutationMeta](type-aliases/MutationMeta.md) +- [MutationObserverResult](type-aliases/MutationObserverResult.md) +- [MutationScope](type-aliases/MutationScope.md) - [MutationStateOptions](type-aliases/MutationStateOptions.md) +- [MutationStatus](type-aliases/MutationStatus.md) +- [NetworkMode](type-aliases/NetworkMode.md) +- [NonUndefinedGuard](type-aliases/NonUndefinedGuard.md) +- [NotifyEventType](type-aliases/NotifyEventType.md) +- [NotifyOnChangeProps](type-aliases/NotifyOnChangeProps.md) +- [OmitKeyof](type-aliases/OmitKeyof.md) +- [Override](type-aliases/Override.md) +- [PlaceholderDataFunction](type-aliases/PlaceholderDataFunction.md) - [QueriesOptions](type-aliases/QueriesOptions.md) - [QueriesPlaceholderDataFunction](type-aliases/QueriesPlaceholderDataFunction.md) - [QueriesResults](type-aliases/QueriesResults.md) +- [QueryBooleanOption](type-aliases/QueryBooleanOption.md) +- [QueryCacheNotifyEvent](type-aliases/QueryCacheNotifyEvent.md) +- [QueryFunction](type-aliases/QueryFunction.md) +- [QueryFunctionContext](type-aliases/QueryFunctionContext.md) +- [QueryKey](type-aliases/QueryKey.md) +- [QueryKeyHashFunction](type-aliases/QueryKeyHashFunction.md) +- [QueryKeyWithDataTag](type-aliases/QueryKeyWithDataTag.md) +- [QueryMeta](type-aliases/QueryMeta.md) +- [QueryObserverResult](type-aliases/QueryObserverResult.md) +- [QueryPersister](type-aliases/QueryPersister.md) +- [QueryStatus](type-aliases/QueryStatus.md) +- [SkipToken](type-aliases/SkipToken.md) +- [StaleTime](type-aliases/StaleTime.md) +- [StaleTimeFunction](type-aliases/StaleTimeFunction.md) +- [ThrowOnError](type-aliases/ThrowOnError.md) +- [TimeoutCallback](type-aliases/TimeoutCallback.md) +- [TimeoutProvider](type-aliases/TimeoutProvider.md) - [UndefinedInitialDataInfiniteOptions](type-aliases/UndefinedInitialDataInfiniteOptions.md) - [UndefinedInitialDataOptions](type-aliases/UndefinedInitialDataOptions.md) - [UnsetMarker](type-aliases/UnsetMarker.md) @@ -81,9 +200,17 @@ title: "@tanstack/angular-query" - [injectMutationState](functions/injectMutationState.md) - [injectQueries](functions/injectQueries.md) - [injectQuery](functions/injectQuery.md) +- [~~isCancelledError~~](functions/isCancelledError.md) +- [keepPreviousData](functions/keepPreviousData.md) +- [matchMutation](functions/matchMutation.md) +- [matchQuery](functions/matchQuery.md) - [mutationOptions](functions/mutationOptions.md) +- [noop](functions/noop.md) +- [partialMatchKey](functions/partialMatchKey.md) - [provideTanStackQuery](functions/provideTanStackQuery.md) - [queryOptions](functions/queryOptions.md) +- [replaceEqualDeep](functions/replaceEqualDeep.md) +- [shouldThrowError](functions/shouldThrowError.md) - [toResource](functions/toResource.md) - [withHydrationKey](functions/withHydrationKey.md) - [withNoQueryHydration](functions/withNoQueryHydration.md) diff --git a/docs/framework/angular/reference/interfaces/BaseInfiniteQueryNarrowing.md b/docs/framework/angular/reference/interfaces/BaseInfiniteQueryNarrowing.md index 252eb9e27b8..c405450bcc7 100644 --- a/docs/framework/angular/reference/interfaces/BaseInfiniteQueryNarrowing.md +++ b/docs/framework/angular/reference/interfaces/BaseInfiniteQueryNarrowing.md @@ -3,7 +3,7 @@ id: BaseInfiniteQueryNarrowing title: BaseInfiniteQueryNarrowing --- -Defined in: [packages/angular-query/src/types.ts:114](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L114) +Defined in: [packages/angular-query/src/types.ts:119](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L119) ## Type Parameters @@ -13,34 +13,12 @@ Defined in: [packages/angular-query/src/types.ts:114](https://github.com/TanStac ### TError -`TError` = `DefaultError` +`TError` = [`DefaultError`](../type-aliases/DefaultError.md) ## Properties -### isError - -```ts -isError: SignalFunction<(this) => this is CreateInfiniteQueryResult>>; -``` - -Defined in: [packages/angular-query/src/types.ts:127](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L127) - -*** - -### isPending - -```ts -isPending: SignalFunction<(this) => this is CreateInfiniteQueryResult>>; -``` - -Defined in: [packages/angular-query/src/types.ts:136](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L136) - -*** - -### isSuccess - -```ts -isSuccess: SignalFunction<(this) => this is CreateInfiniteQueryResult>>; -``` - -Defined in: [packages/angular-query/src/types.ts:118](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L118) +| Property | Type | +| ------ | ------ | +| `isError` | `SignalFunction`\<(`this`: [`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\<`TData`, `TError`\>) => `this is CreateInfiniteQueryResult>`\> | +| `isPending` | `SignalFunction`\<(`this`: [`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\<`TData`, `TError`\>) => `this is CreateInfiniteQueryResult>`\> | +| `isSuccess` | `SignalFunction`\<(`this`: [`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\<`TData`, `TError`\>) => `this is CreateInfiniteQueryResult>`\> | diff --git a/docs/framework/angular/reference/interfaces/BaseMutationNarrowing.md b/docs/framework/angular/reference/interfaces/BaseMutationNarrowing.md index af8dfb3884d..a80fc63072c 100644 --- a/docs/framework/angular/reference/interfaces/BaseMutationNarrowing.md +++ b/docs/framework/angular/reference/interfaces/BaseMutationNarrowing.md @@ -3,7 +3,7 @@ id: BaseMutationNarrowing title: BaseMutationNarrowing --- -Defined in: [packages/angular-query/src/types.ts:297](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L297) +Defined in: [packages/angular-query/src/types.ts:386](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L386) ## Type Parameters @@ -11,63 +11,23 @@ Defined in: [packages/angular-query/src/types.ts:297](https://github.com/TanStac `TData` = `unknown` -The type your mutation function resolves to. - ### TError `TError` = [`DefaultError`](../type-aliases/DefaultError.md) -The type of errors your mutation function may throw. - ### TVariables `TVariables` = `unknown` -The type of the variable passed to `mutate`/`mutateAsync`. - ### TOnMutateResult `TOnMutateResult` = `unknown` -The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as -their `onMutateResult` parameter — useful for optimistic-update rollback data. - ## Properties -### isError - -```ts -isError: SignalFunction<(this) => this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>>; -``` - -Defined in: [packages/angular-query/src/types.ts:320](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L320) - -*** - -### isIdle - -```ts -isIdle: SignalFunction<(this) => this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>>; -``` - -Defined in: [packages/angular-query/src/types.ts:354](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L354) - -*** - -### isPending - -```ts -isPending: SignalFunction<(this) => this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>>; -``` - -Defined in: [packages/angular-query/src/types.ts:337](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L337) - -*** - -### isSuccess - -```ts -isSuccess: SignalFunction<(this) => this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>>; -``` - -Defined in: [packages/angular-query/src/types.ts:303](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L303) +| Property | Type | +| ------ | ------ | +| `isError` | `SignalFunction`\<(`this`: [`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>) => `this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>`\> | +| `isIdle` | `SignalFunction`\<(`this`: [`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>) => `this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>`\> | +| `isPending` | `SignalFunction`\<(`this`: [`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>) => `this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>`\> | +| `isSuccess` | `SignalFunction`\<(`this`: [`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>) => `this is CreateMutationResult, { mutate: CreateMutateFunction }> & { mutateAsync: CreateMutateAsyncFunction }>`\> | diff --git a/docs/framework/angular/reference/interfaces/BaseQueryNarrowing.md b/docs/framework/angular/reference/interfaces/BaseQueryNarrowing.md index 38ffb777ec0..802fb38400d 100644 --- a/docs/framework/angular/reference/interfaces/BaseQueryNarrowing.md +++ b/docs/framework/angular/reference/interfaces/BaseQueryNarrowing.md @@ -3,7 +3,7 @@ id: BaseQueryNarrowing title: BaseQueryNarrowing --- -Defined in: [packages/angular-query/src/types.ts:60](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L60) +Defined in: [packages/angular-query/src/types.ts:65](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L65) ## Type Parameters @@ -11,40 +11,14 @@ Defined in: [packages/angular-query/src/types.ts:60](https://github.com/TanStack `TData` = `unknown` -The type `data` ends up as after `select` runs. - ### TError `TError` = [`DefaultError`](../type-aliases/DefaultError.md) -The type of errors your `queryFn` may throw. - ## Properties -### isError - -```ts -isError: SignalFunction<(this) => this is CreateBaseQueryResult>>; -``` - -Defined in: [packages/angular-query/src/types.ts:70](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L70) - -*** - -### isPending - -```ts -isPending: SignalFunction<(this) => this is CreateBaseQueryResult>>; -``` - -Defined in: [packages/angular-query/src/types.ts:79](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L79) - -*** - -### isSuccess - -```ts -isSuccess: SignalFunction<(this) => this is CreateBaseQueryResult>>; -``` - -Defined in: [packages/angular-query/src/types.ts:61](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L61) +| Property | Type | +| ------ | ------ | +| `isError` | `SignalFunction`\<(`this`: [`CreateBaseQueryResult`](../type-aliases/CreateBaseQueryResult.md)\<`TData`, `TError`\>) => `this is CreateBaseQueryResult>`\> | +| `isPending` | `SignalFunction`\<(`this`: [`CreateBaseQueryResult`](../type-aliases/CreateBaseQueryResult.md)\<`TData`, `TError`\>) => `this is CreateBaseQueryResult>`\> | +| `isSuccess` | `SignalFunction`\<(`this`: [`CreateBaseQueryResult`](../type-aliases/CreateBaseQueryResult.md)\<`TData`, `TError`\>) => `this is CreateBaseQueryResult>`\> | diff --git a/docs/framework/angular/reference/interfaces/CancelOptions.md b/docs/framework/angular/reference/interfaces/CancelOptions.md index bddacd0481a..4483d1078ac 100644 --- a/docs/framework/angular/reference/interfaces/CancelOptions.md +++ b/docs/framework/angular/reference/interfaces/CancelOptions.md @@ -3,10 +3,7 @@ id: CancelOptions title: CancelOptions --- -Defined in: [packages/query-core/src/types.ts:1645](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1645) - -Options for cancelling an in-flight fetch, e.g. via `query.cancel()`. -They are carried on the [CancelledError](../classes/CancelledError.md) that the cancelled fetch rejects with. +Defined in: packages/query-core/dist-ts/src/types.d.ts:933 ## Properties diff --git a/docs/framework/angular/reference/interfaces/CreateInfiniteQueryOptions.md b/docs/framework/angular/reference/interfaces/CreateInfiniteQueryOptions.md index 119ea6792d0..6be5be70d8f 100644 --- a/docs/framework/angular/reference/interfaces/CreateInfiniteQueryOptions.md +++ b/docs/framework/angular/reference/interfaces/CreateInfiniteQueryOptions.md @@ -3,11 +3,11 @@ id: CreateInfiniteQueryOptions title: CreateInfiniteQueryOptions --- -Defined in: [packages/angular-query/src/types.ts:174](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L174) +Defined in: [packages/angular-query/src/types.ts:179](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L179) ## Extends -- `OmitKeyof`\<`InfiniteQueryObserverOptions`\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>, `"notifyOnChangeProps"` \| `"suspense"` \| `"throwOnError"`\> +- [`OmitKeyof`](../type-aliases/OmitKeyof.md)\<[`InfiniteQueryObserverOptions`](InfiniteQueryObserverOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>, `"notifyOnChangeProps"` \| `"suspense"` \| `"throwOnError"`\> ## Type Parameters @@ -15,64 +15,50 @@ Defined in: [packages/angular-query/src/types.ts:174](https://github.com/TanStac `TQueryFnData` = `unknown` -The type of a single page, as your `queryFn` resolves it. - ### TError `TError` = [`DefaultError`](../type-aliases/DefaultError.md) -The type of errors your `queryFn` may throw. - ### TData `TData` = `TQueryFnData` -The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` here, though -`injectInfiniteQuery` itself defaults it to `InfiniteData` — the shape `data` actually has -when no `select` is used. - ### TQueryKey `TQueryKey` *extends* [`QueryKey`](../type-aliases/QueryKey.md) = [`QueryKey`](../type-aliases/QueryKey.md) -The type of your `queryKey`. - ### TPageParam `TPageParam` = `unknown` -The type of the parameter passed to `queryFn` to fetch a given page. - ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `enabled?` | \| `false` \| `true` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` | `true` | Set this to `false` or a function that returns `false` to disable automatic refetching when the query mounts or changes query keys. To refetch the query, use the `refetch` method returned from the `useQuery` instance. Accepts a boolean or function that returns a boolean. | -| `gcTime?` | `number` | `undefined` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | -| `getNextPageParam` | (`lastPage`: `TQueryFnData`, `allPages`: `TQueryFnData`[], `lastPageParam`: `TPageParam`, `allPageParams`: `TPageParam`[]) => `TPageParam` \| `null` \| `undefined` | `undefined` | This function can be set to automatically get the next cursor for infinite queries. The result will also be used to determine the value of `hasNextPage`. | -| `getPreviousPageParam?` | (`firstPage`: `TQueryFnData`, `allPages`: `TQueryFnData`[], `firstPageParam`: `TPageParam`, `allPageParams`: `TPageParam`[]) => `TPageParam` \| `null` \| `undefined` | `undefined` | This function can be set to automatically get the previous cursor for infinite queries. The result will also be used to determine the value of `hasPreviousPage`. | -| `initialData?` | \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| () => \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| `undefined` | `undefined` | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | -| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | -| `initialPageParam` | `TPageParam` | `undefined` | The page param to start from when an infinite query has no pages yet. It is passed to `queryFn` as `pageParam` for the first page; every page after that gets the value returned by `getNextPageParam` or `getPreviousPageParam`. It only applies while the query has no pages: once a first page exists, refetching starts from that page's own param instead. | -| `maxPages?` | `number` | `undefined` | Maximum number of pages to store in the data of an infinite query. | -| `meta?` | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | -| `networkMode?` | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a query is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| `notifyOnChangeProps?` | \| ( \| `"error"` \| `"data"` \| `"isError"` \| `"isPending"` \| `"isLoading"` \| `"isLoadingError"` \| `"isRefetchError"` \| `"isSuccess"` \| `"isPlaceholderData"` \| `"status"` \| `"dataUpdatedAt"` \| `"errorUpdatedAt"` \| `"failureCount"` \| `"failureReason"` \| `"errorUpdateCount"` \| `"isFetched"` \| `"isFetchedAfterMount"` \| `"isFetching"` \| `"isInitialLoading"` \| `"isPaused"` \| `"isRefetching"` \| `"isStale"` \| `"isEnabled"` \| `"refetch"` \| `"fetchStatus"` \| `"fetchNextPage"` \| `"fetchPreviousPage"` \| `"hasNextPage"` \| `"hasPreviousPage"` \| `"isFetchNextPageError"` \| `"isFetchingNextPage"` \| `"isFetchPreviousPageError"` \| `"isFetchingPreviousPage"`)[] \| `"all"` \| () => \| `"all"` \| ( \| `"error"` \| `"data"` \| `"isError"` \| `"isPending"` \| `"isLoading"` \| `"isLoadingError"` \| `"isRefetchError"` \| `"isSuccess"` \| `"isPlaceholderData"` \| `"status"` \| `"dataUpdatedAt"` \| `"errorUpdatedAt"` \| `"failureCount"` \| `"failureReason"` \| `"errorUpdateCount"` \| `"isFetched"` \| `"isFetchedAfterMount"` \| `"isFetching"` \| `"isInitialLoading"` \| `"isPaused"` \| `"isRefetching"` \| `"isStale"` \| `"isEnabled"` \| `"refetch"` \| `"fetchStatus"` \| `"fetchNextPage"` \| `"fetchPreviousPage"` \| `"hasNextPage"` \| `"hasPreviousPage"` \| `"isFetchNextPageError"` \| `"isFetchingNextPage"` \| `"isFetchPreviousPageError"` \| `"isFetchingPreviousPage"`)[] \| `undefined` | `undefined` | If set, the component will only re-render if any of the listed properties change. When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change. When set to `'all'`, the component will re-render whenever a query is updated. When set to a function, the function will be executed to compute the list of properties. Defaults to `undefined`, in which case property access is tracked automatically, and the component only re-renders when one of the tracked properties changes. | -| `persister?` | (`queryFn`: (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`NoInfer`\<`TQueryKey`\>, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\>, `context`: `object`, `query`: [`Query`](../classes/Query.md)) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | -| `placeholderData?` | \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| (`previousData`: \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| `undefined`, `previousQuery`: \| [`Query`](../classes/Query.md)\<[`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\> \| `undefined`) => \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| `undefined` | `undefined` | If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `loading` data and no initialData has been provided. | -| `queryFn?` | \| *typeof* [`skipToken`](../variables/skipToken.md) \| (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`TQueryKey`, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | -| `queryHash?` | `string` | `undefined` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | -| `queryKey` | `TQueryKey` & `object` | `undefined` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | -| `queryKeyHashFn?` | (`queryKey`: `TQueryKey`) => `string` | `undefined` | If specified, this function is used to hash the `queryKey` to a string. | -| `refetchInterval?` | \| `number` \| `false` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `number` \| `false` \| `undefined` | `false` | If set to a number, the query will continuously refetch at this frequency in milliseconds. If set to a function, the function will be executed with the latest data and query to compute a frequency | -| `refetchIntervalInBackground?` | `boolean` | `false` | If set to `true`, the query will continue to refetch while their tab/window is in the background. | -| `refetchOnMount?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | `true` | If set to `true`, the query will refetch on mount if the data is stale. If set to `false`, will disable additional instances of a query to trigger background refetch. If set to `'always'`, the query will always refetch on mount (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value | -| `refetchOnReconnect?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | `undefined` | If set to `true`, the query will refetch on reconnect if the data is stale. If set to `false`, the query will not refetch on reconnect. If set to `'always'`, the query will always refetch on reconnect (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. Defaults to `true` unless `networkMode` is `'always'`. | -| `refetchOnWindowFocus?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | `true` | If set to `true`, the query will refetch on window focus if the data is stale. If set to `false`, the query will not refetch on window focus. If set to `'always'`, the query will always refetch on window focus (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. | -| `retry?` | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `undefined` | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | -| `retryDelay?` | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| `retryOnMount?` | \| `false` \| `true` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` | `true` | If set to `false`, the query will not be retried on mount if it contains an error. If set to a function, the function will be executed with the query to compute the value. | -| `select?` | (`data`: [`InfiniteData`](InfiniteData.md)) => `TData` | `undefined` | This option can be used to transform or select a part of the data returned by the query function. It affects the returned `data` value, but does not affect what gets stored in the query cache. The `select` function will only run if `data` changed, or if the reference to the `select` function itself changes. To optimize, memoize the function so its reference stays stable across calls. | -| `staleTime?` | \| `number` \| `"static"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `number` \| `"static"` | `0` | The time in milliseconds after data is considered stale. If set to `Infinity`, the data will never be considered stale. If set to `'static'`, the data will never be considered stale. If set to a function, the function will be executed with the query to compute a `staleTime`. | -| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | `true` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. | -| `throwOnError?` | \| `false` \| `true` \| (`error`: `TError`, `query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` | `false` | Whether errors should be thrown instead of setting the `error` property. If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary. If set to `false` and `suspense` is `false`, errors are returned as state. If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`). | +| Property | Type | Description | +| ------ | ------ | ------ | +| `enabled?` | [`QueryBooleanOption`](../type-aliases/QueryBooleanOption.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\> | Set this to `false` or a function that returns `false` to disable automatic refetching when the query mounts or changes query keys. To refetch the query, use the `refetch` method returned from the `useQuery` instance. Accepts a boolean or function that returns a boolean. Defaults to `true`. | +| `gcTime?` | `number` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | +| `getNextPageParam` | [`GetNextPageParamFunction`](../type-aliases/GetNextPageParamFunction.md)\<`TPageParam`, `TQueryFnData`\> | This function can be set to automatically get the next cursor for infinite queries. The result will also be used to determine the value of `hasNextPage`. | +| `getPreviousPageParam?` | [`GetPreviousPageParamFunction`](../type-aliases/GetPreviousPageParamFunction.md)\<`TPageParam`, `TQueryFnData`\> | This function can be set to automatically get the previous cursor for infinite queries. The result will also be used to determine the value of `hasPreviousPage`. | +| `initialData?` | \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| [`InitialDataFunction`](../type-aliases/InitialDataFunction.md)\<[`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>\> | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | +| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | +| `initialPageParam` | `TPageParam` | - | +| `maxPages?` | `number` | Maximum number of pages to store in the data of an infinite query. | +| `meta?` | `Record`\<`string`, `unknown`\> | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | +| `networkMode?` | [`NetworkMode`](../type-aliases/NetworkMode.md) | Controls whether a query is allowed to run based on the current network connectivity. Defaults to `'online'`. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| `persister?` | [`QueryPersister`](../type-aliases/QueryPersister.md)\<`TQueryFnData`, `NoInfer`\<`TQueryKey`\>, `TPageParam`\> | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | +| `placeholderData?` | \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| [`PlaceholderDataFunction`](../type-aliases/PlaceholderDataFunction.md)\<[`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\> | If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `loading` data and no initialData has been provided. | +| `queryFn?` | \| *typeof* [`skipToken`](../variables/skipToken.md) \| [`QueryFunction`](../type-aliases/QueryFunction.md)\<`TQueryFnData`, `TQueryKey`, `TPageParam`\> | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | +| `queryHash?` | `string` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | +| `queryKey` | `TQueryKey` & `object` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | +| `queryKeyHashFn?` | [`QueryKeyHashFunction`](../type-aliases/QueryKeyHashFunction.md)\<`TQueryKey`\> | If specified, this function is used to hash the `queryKey` to a string. | +| `refetchInterval?` | \| `number` \| `false` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `number` \| `false` \| `undefined` | If set to a number, the query will continuously refetch at this frequency in milliseconds. If set to a function, the function will be executed with the latest data and query to compute a frequency Defaults to `false`. | +| `refetchIntervalInBackground?` | `boolean` | If set to `true`, the query will continue to refetch while their tab/window is in the background. Defaults to `false`. | +| `refetchOnMount?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | If set to `true`, the query will refetch on mount if the data is stale. If set to `false`, will disable additional instances of a query to trigger background refetch. If set to `'always'`, the query will always refetch on mount (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value Defaults to `true`. | +| `refetchOnReconnect?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | If set to `true`, the query will refetch on reconnect if the data is stale. If set to `false`, the query will not refetch on reconnect. If set to `'always'`, the query will always refetch on reconnect (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. Defaults to `true` unless `networkMode` is `'always'`. | +| `refetchOnWindowFocus?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | If set to `true`, the query will refetch on window focus if the data is stale. If set to `false`, the query will not refetch on window focus. If set to `'always'`, the query will always refetch on window focus (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. Defaults to `true`. | +| `retry?` | `RetryValue`\<`TError`\> | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | +| `retryDelay?` | `RetryDelayValue`\<`TError`\> | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | +| `retryOnMount?` | [`QueryBooleanOption`](../type-aliases/QueryBooleanOption.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\> | If set to `false`, the query will not be retried on mount if it contains an error. If set to a function, the function will be executed with the query to compute the value. Defaults to `true`. | +| `select?` | (`data`: [`InfiniteData`](InfiniteData.md)) => `TData` | This option can be used to transform or select a part of the data returned by the query function. It affects the returned `data` value, but does not affect what gets stored in the query cache. The `select` function will only run if `data` changed, or if the reference to the `select` function itself changes. To optimize, memoize the function so its reference stays stable across calls. | +| `staleTime?` | [`StaleTimeFunction`](../type-aliases/StaleTimeFunction.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\> | The time in milliseconds after data is considered stale. If set to `Infinity`, the data will never be considered stale. If set to `'static'`, the data will never be considered stale. If set to a function, the function will be executed with the query to compute a `staleTime`. Defaults to `0`. | +| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. Defaults to `true`. | diff --git a/docs/framework/angular/reference/interfaces/CreateMutationOptions.md b/docs/framework/angular/reference/interfaces/CreateMutationOptions.md index ca80deb6903..7454c0d6582 100644 --- a/docs/framework/angular/reference/interfaces/CreateMutationOptions.md +++ b/docs/framework/angular/reference/interfaces/CreateMutationOptions.md @@ -3,11 +3,14 @@ id: CreateMutationOptions title: CreateMutationOptions --- -Defined in: [packages/angular-query/src/types.ts:241](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L241) +Defined in: [packages/angular-query/src/types.ts:295](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L295) + +The options accepted by `injectMutation`. Same as [MutationObserverOptions](MutationObserverOptions.md) from +`@tanstack/query-core`, minus the internal `_defaulted` flag. ## Extends -- `OmitKeyof`\<`MutationObserverOptions`\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>, `"_defaulted"` \| `"throwOnError"`\> +- [`OmitKeyof`](../type-aliases/OmitKeyof.md)\<[`MutationObserverOptions`](MutationObserverOptions.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>, `"_defaulted"` \| `"throwOnError"`\> ## Type Parameters @@ -38,18 +41,17 @@ their `onMutateResult` parameter — useful for optimistic-update rollback data. ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `gcTime?` | `number` | `undefined` | The time in milliseconds that an unused/inactive mutation remains in memory before it is garbage collected. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. | -| `meta?` | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on the mutation cache entry. Use it to pass information that can be read wherever the `mutation` is available, such as the `onError` and `onSuccess` callbacks of the `MutationCache`. | -| `mutationFn?` | (`variables`: `TVariables`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `Promise`\<`TData`\> | `undefined` | The function that performs the asynchronous task this mutation runs. Required, unless a default mutation function has been set for the matching `mutationKey` via `queryClient.setMutationDefaults`. Receives the `variables` passed to `mutate`, and a [MutationFunctionContext](../type-aliases/MutationFunctionContext.md) holding the `QueryClient`, the `mutationKey` and `meta`. Must return a promise that resolves the mutation's data. | -| `mutationKey?` | readonly `unknown`[] | `undefined` | The key to use for this mutation. Optional, but required to inherit defaults registered with `queryClient.setMutationDefaults`, and to match this mutation with `useMutationState` or `queryClient.isMutating`. | -| `networkMode?` | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a mutation is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| `onError?` | (`error`: `TError`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | `undefined` | This function fires when the mutation encounters an error, and is passed the error. If a promise is returned, it is awaited before `onSettled` runs. | -| `onMutate?` | (`variables`: `TVariables`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `TOnMutateResult` \| `Promise`\<`TOnMutateResult`\> | `undefined` | This function fires before the mutation function runs, and receives the same variables. Useful for optimistic updates applied in the hope that the mutation succeeds. The value it returns is passed to `onSuccess`, `onError` and `onSettled` as `onMutateResult`, which is where an optimistic update is usually rolled back. If a promise is returned, it is awaited before the mutation function runs. | -| `onSettled?` | (`data`: `TData` \| `undefined`, `error`: `TError` \| `null`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | `undefined` | This function fires when the mutation either succeeds or errors, and is passed either the data or the error. If a promise is returned, it is awaited before the mutation settles. | -| `onSuccess?` | (`data`: `TData`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | `undefined` | This function fires when the mutation succeeds, and is passed the mutation's result. If a promise is returned, it is awaited before `onSettled` runs. | -| `retry?` | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `0` | If `false`, failed mutations will not retry by default. If `true`, failed mutations will retry infinitely. If set to an integer number, e.g. 3, failed mutations will retry until the failed mutation count meets that number. If set to a function `(failureCount, error) => boolean` failed mutations will retry until the function returns false. | -| `retryDelay?` | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| `scope?` | [`MutationScope`](../type-aliases/MutationScope.md) | `undefined` | Controls whether this mutation runs alongside others or waits its turn. Mutations sharing the same `scope.id` run serially, in the order they were started. Without a scope, a mutation runs as soon as it is triggered. | -| `throwOnError?` | `boolean` \| (`error`: `TError`) => `boolean` | `false` | Whether errors should be thrown instead of setting the `error` property. If set to `true`, all errors will be thrown to the nearest error boundary. If set to a function, it will be passed the error and should return a boolean indicating whether to throw the error (`true`) or return it as state (`false`). | +| Property | Type | Description | +| ------ | ------ | ------ | +| `gcTime?` | `number` | The time in milliseconds that an unused/inactive mutation remains in memory before it is garbage collected. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. | +| `meta?` | `Record`\<`string`, `unknown`\> | - | +| `mutationFn?` | [`MutationFunction`](../type-aliases/MutationFunction.md)\<`TData`, `TVariables`\> | - | +| `mutationKey?` | readonly `unknown`[] | - | +| `networkMode?` | [`NetworkMode`](../type-aliases/NetworkMode.md) | Controls whether a mutation is allowed to run based on the current network connectivity. Defaults to `'online'`. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| `onError?` | (`error`: `TError`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | - | +| `onMutate?` | (`variables`: `TVariables`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `TOnMutateResult` \| `Promise`\<`TOnMutateResult`\> | - | +| `onSettled?` | (`data`: `TData` \| `undefined`, `error`: `TError` \| `null`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | - | +| `onSuccess?` | (`data`: `TData`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | - | +| `retry?` | `RetryValue`\<`TError`\> | If `false`, failed mutations will not retry by default. If `true`, failed mutations will retry infinitely. If set to an integer number, e.g. 3, failed mutations will retry until the failed mutation count meets that number. If set to a function `(failureCount, error) => boolean` failed mutations will retry until the function returns false. Defaults to `0`. | +| `retryDelay?` | `RetryDelayValue`\<`TError`\> | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. Defaults to a function that applies exponential backoff, capped at 30 seconds. | +| `scope?` | [`MutationScope`](../type-aliases/MutationScope.md) | - | diff --git a/docs/framework/angular/reference/interfaces/DefaultOptions.md b/docs/framework/angular/reference/interfaces/DefaultOptions.md index 569989be69f..2e0e3c4f931 100644 --- a/docs/framework/angular/reference/interfaces/DefaultOptions.md +++ b/docs/framework/angular/reference/interfaces/DefaultOptions.md @@ -3,7 +3,7 @@ id: DefaultOptions title: DefaultOptions --- -Defined in: [packages/query-core/src/types.ts:1627](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1627) +Defined in: packages/query-core/dist-ts/src/types.d.ts:923 ## Type Parameters @@ -21,4 +21,4 @@ Defined in: [packages/query-core/src/types.ts:1627](https://github.com/TanStack/ | `hydrate.mutations?` | [`MutationOptions`](MutationOptions.md)\<`unknown`, `Error`, `unknown`, `unknown`\> | Default options merged into every mutation restored from the dehydrated state. | | `hydrate.queries?` | [`QueryOptions`](QueryOptions.md)\<`unknown`, `Error`, `unknown`, readonly `unknown`[], `never`\> | Default options merged into every query restored from the dehydrated state. | | `mutations?` | [`MutationObserverOptions`](MutationObserverOptions.md)\<`unknown`, `TError`, `unknown`, `unknown`\> | Default options applied to every mutation, unless overridden per-mutation. | -| `queries?` | [`OmitKeyof`](../type-aliases/OmitKeyof.md)\<[`QueryObserverOptions`](QueryObserverOptions.md)\<`unknown`, `TError`, `unknown`, `unknown`, readonly `unknown`[], `never`\>, `"queryKey"` \| `"suspense"`, `"strictly"`\> | Default options applied to every query, unless overridden per-query. | +| `queries?` | [`OmitKeyof`](../type-aliases/OmitKeyof.md)\<[`QueryObserverOptions`](QueryObserverOptions.md)\<`unknown`, `TError`, `unknown`, `unknown`, readonly `unknown`[], `never`\>, `"suspense"` \| `"queryKey"`, `"strictly"`\> | Default options applied to every query, unless overridden per-query. | diff --git a/docs/framework/angular/reference/interfaces/DefinedInfiniteQueryNarrowing.md b/docs/framework/angular/reference/interfaces/DefinedInfiniteQueryNarrowing.md index a2057b81868..377b785413e 100644 --- a/docs/framework/angular/reference/interfaces/DefinedInfiniteQueryNarrowing.md +++ b/docs/framework/angular/reference/interfaces/DefinedInfiniteQueryNarrowing.md @@ -3,7 +3,7 @@ id: DefinedInfiniteQueryNarrowing title: DefinedInfiniteQueryNarrowing --- -Defined in: [packages/angular-query/src/types.ts:147](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L147) +Defined in: [packages/angular-query/src/types.ts:152](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L152) ## Type Parameters @@ -13,34 +13,12 @@ Defined in: [packages/angular-query/src/types.ts:147](https://github.com/TanStac ### TError -`TError` = `DefaultError` +`TError` = [`DefaultError`](../type-aliases/DefaultError.md) ## Properties -### isError - -```ts -isError: SignalFunction<(this) => this is DefinedCreateInfiniteQueryResult>>; -``` - -Defined in: [packages/angular-query/src/types.ts:160](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L160) - -*** - -### isPending - -```ts -isPending: SignalFunction<(this) => this is never>; -``` - -Defined in: [packages/angular-query/src/types.ts:169](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L169) - -*** - -### isSuccess - -```ts -isSuccess: SignalFunction<(this) => this is DefinedCreateInfiniteQueryResult>>; -``` - -Defined in: [packages/angular-query/src/types.ts:151](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L151) +| Property | Type | +| ------ | ------ | +| `isError` | `SignalFunction`\<(`this`: [`DefinedCreateInfiniteQueryResult`](../type-aliases/DefinedCreateInfiniteQueryResult.md)\<`TData`, `TError`\>) => `this is DefinedCreateInfiniteQueryResult>`\> | +| `isPending` | `SignalFunction`\<(`this`: [`DefinedCreateInfiniteQueryResult`](../type-aliases/DefinedCreateInfiniteQueryResult.md)\<`TData`, `TError`\>) => `this is never`\> | +| `isSuccess` | `SignalFunction`\<(`this`: [`DefinedCreateInfiniteQueryResult`](../type-aliases/DefinedCreateInfiniteQueryResult.md)\<`TData`, `TError`\>) => `this is DefinedCreateInfiniteQueryResult>`\> | diff --git a/docs/framework/angular/reference/interfaces/DefinedQueryNarrowing.md b/docs/framework/angular/reference/interfaces/DefinedQueryNarrowing.md index ee6773e5df2..2229813deb9 100644 --- a/docs/framework/angular/reference/interfaces/DefinedQueryNarrowing.md +++ b/docs/framework/angular/reference/interfaces/DefinedQueryNarrowing.md @@ -3,7 +3,7 @@ id: DefinedQueryNarrowing title: DefinedQueryNarrowing --- -Defined in: [packages/angular-query/src/types.ts:90](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L90) +Defined in: [packages/angular-query/src/types.ts:95](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L95) ## Type Parameters @@ -13,34 +13,12 @@ Defined in: [packages/angular-query/src/types.ts:90](https://github.com/TanStack ### TError -`TError` = `DefaultError` +`TError` = [`DefaultError`](../type-aliases/DefaultError.md) ## Properties -### isError - -```ts -isError: SignalFunction<(this) => this is DefinedCreateQueryResult>>; -``` - -Defined in: [packages/angular-query/src/types.ts:100](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L100) - -*** - -### isPending - -```ts -isPending: SignalFunction<(this) => this is never>; -``` - -Defined in: [packages/angular-query/src/types.ts:109](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L109) - -*** - -### isSuccess - -```ts -isSuccess: SignalFunction<(this) => this is DefinedCreateQueryResult>>; -``` - -Defined in: [packages/angular-query/src/types.ts:91](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L91) +| Property | Type | +| ------ | ------ | +| `isError` | `SignalFunction`\<(`this`: [`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<`TData`, `TError`\>) => `this is DefinedCreateQueryResult>`\> | +| `isPending` | `SignalFunction`\<(`this`: [`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<`TData`, `TError`\>) => `this is never`\> | +| `isSuccess` | `SignalFunction`\<(`this`: [`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<`TData`, `TError`\>) => `this is DefinedCreateQueryResult>`\> | diff --git a/docs/framework/angular/reference/interfaces/DehydrateOptions.md b/docs/framework/angular/reference/interfaces/DehydrateOptions.md index 23717093d3c..0dd8ecc23d7 100644 --- a/docs/framework/angular/reference/interfaces/DehydrateOptions.md +++ b/docs/framework/angular/reference/interfaces/DehydrateOptions.md @@ -3,7 +3,7 @@ id: DehydrateOptions title: DehydrateOptions --- -Defined in: [packages/query-core/src/hydration.ts:42](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L42) +Defined in: packages/query-core/dist-ts/src/hydration.d.ts:10 Options for `dehydrate`, controlling which queries/mutations are included in the resulting `DehydratedState` and how their data/errors are transformed before being serialized (e.g. for embedding in server-rendered markup). diff --git a/docs/framework/angular/reference/interfaces/DehydratedState.md b/docs/framework/angular/reference/interfaces/DehydratedState.md index 8668325a628..aa875116d3f 100644 --- a/docs/framework/angular/reference/interfaces/DehydratedState.md +++ b/docs/framework/angular/reference/interfaces/DehydratedState.md @@ -3,7 +3,7 @@ id: DehydratedState title: DehydratedState --- -Defined in: [packages/query-core/src/hydration.ts:95](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L95) +Defined in: packages/query-core/dist-ts/src/hydration.d.ts:58 A serializable snapshot of a `QueryClient`'s cache, as produced by `dehydrate` and consumed by `hydrate`. Typically transported from server to client (e.g. embedded in server-rendered markup) to seed the client's cache with data diff --git a/docs/framework/angular/reference/interfaces/EnsureQueryDataOptions.md b/docs/framework/angular/reference/interfaces/EnsureQueryDataOptions.md index c8061a6de23..7477414c85f 100644 --- a/docs/framework/angular/reference/interfaces/EnsureQueryDataOptions.md +++ b/docs/framework/angular/reference/interfaces/EnsureQueryDataOptions.md @@ -3,7 +3,7 @@ id: EnsureQueryDataOptions title: EnsureQueryDataOptions --- -Defined in: [packages/query-core/src/types.ts:673](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L673) +Defined in: packages/query-core/dist-ts/src/types.d.ts:341 ## Deprecated @@ -35,22 +35,22 @@ Defined in: [packages/query-core/src/types.ts:673](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| ~~`gcTime?`~~ | `number` | `undefined` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | -| ~~`initialData?`~~ | `TData` \| () => `TData` \| `undefined` | `undefined` | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | -| ~~`initialDataUpdatedAt?`~~ | `number` \| () => `number` \| `undefined` | `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | -| ~~`initialPageParam?`~~ | `undefined` | `undefined` | - | -| ~~`maxPages?`~~ | `number` | `undefined` | Maximum number of pages to store in the data of an infinite query. | -| ~~`meta?`~~ | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | -| ~~`networkMode?`~~ | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a query is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| ~~`persister?`~~ | (`queryFn`: (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`NoInfer`\<`TQueryKey`\>, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\>, `context`: `object`, `query`: [`Query`](../classes/Query.md)) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | -| ~~`queryFn?`~~ | \| *typeof* [`skipToken`](../variables/skipToken.md) \| (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`TQueryKey`, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | -| ~~`queryHash?`~~ | `string` | `undefined` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | -| ~~`queryKey`~~ | `TQueryKey` & `object` | `undefined` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | -| ~~`queryKeyHashFn?`~~ | (`queryKey`: `TQueryKey`) => `string` | `undefined` | If specified, this function is used to hash the `queryKey` to a string. | -| ~~`retry?`~~ | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `undefined` | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | -| ~~`retryDelay?`~~ | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| ~~`revalidateIfStale?`~~ | `boolean` | `undefined` | - | -| ~~`staleTime?`~~ | \| `number` \| `"static"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>) => `number` \| `"static"` | `undefined` | The time in milliseconds after data is considered stale. If the data is fresh it will be returned from the cache. | -| ~~`structuralSharing?`~~ | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | `true` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. | +| Property | Type | Description | +| ------ | ------ | ------ | +| ~~`gcTime?`~~ | `number` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | +| ~~`initialData?`~~ | \| `TData` \| [`InitialDataFunction`](../type-aliases/InitialDataFunction.md)\<`TData`\> | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | +| ~~`initialDataUpdatedAt?`~~ | `number` \| () => `number` \| `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | +| ~~`initialPageParam?`~~ | `undefined` | - | +| ~~`maxPages?`~~ | `number` | Maximum number of pages to store in the data of an infinite query. | +| ~~`meta?`~~ | `Record`\<`string`, `unknown`\> | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | +| ~~`networkMode?`~~ | [`NetworkMode`](../type-aliases/NetworkMode.md) | Controls whether a query is allowed to run based on the current network connectivity. Defaults to `'online'`. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| ~~`persister?`~~ | [`QueryPersister`](../type-aliases/QueryPersister.md)\<`TQueryFnData`, `NoInfer`\<`TQueryKey`\>, `TPageParam`\> | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | +| ~~`queryFn?`~~ | \| *typeof* [`skipToken`](../variables/skipToken.md) \| [`QueryFunction`](../type-aliases/QueryFunction.md)\<`TQueryFnData`, `TQueryKey`, `TPageParam`\> | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | +| ~~`queryHash?`~~ | `string` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | +| ~~`queryKey`~~ | `TQueryKey` & `object` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | +| ~~`queryKeyHashFn?`~~ | [`QueryKeyHashFunction`](../type-aliases/QueryKeyHashFunction.md)\<`TQueryKey`\> | If specified, this function is used to hash the `queryKey` to a string. | +| ~~`retry?`~~ | `RetryValue`\<`TError`\> | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | +| ~~`retryDelay?`~~ | `RetryDelayValue`\<`TError`\> | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | +| ~~`revalidateIfStale?`~~ | `boolean` | - | +| ~~`staleTime?`~~ | [`StaleTimeFunction`](../type-aliases/StaleTimeFunction.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> | The time in milliseconds after data is considered stale. If the data is fresh it will be returned from the cache. | +| ~~`structuralSharing?`~~ | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. Defaults to `true`. | diff --git a/docs/framework/angular/reference/interfaces/FetchNextPageOptions.md b/docs/framework/angular/reference/interfaces/FetchNextPageOptions.md index d5c11b9e6c5..d9a36f5c416 100644 --- a/docs/framework/angular/reference/interfaces/FetchNextPageOptions.md +++ b/docs/framework/angular/reference/interfaces/FetchNextPageOptions.md @@ -3,7 +3,7 @@ id: FetchNextPageOptions title: FetchNextPageOptions --- -Defined in: [packages/query-core/src/types.ts:797](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L797) +Defined in: packages/query-core/dist-ts/src/types.d.ts:394 ## Extends @@ -11,7 +11,7 @@ Defined in: [packages/query-core/src/types.ts:797](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `cancelRefetch?` | `boolean` | `true` | If set to `true`, calling `fetchNextPage` repeatedly will invoke `queryFn` every time, whether the previous invocation has resolved or not. Also, the result from previous invocations will be ignored. If set to `false`, calling `fetchNextPage` repeatedly won't have any effect until the first invocation has resolved. | -| `throwOnError?` | `boolean` | `false` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. If set to `false`, failed refetches are swallowed and not surfaced to the caller. | +| Property | Type | Description | +| ------ | ------ | ------ | +| `cancelRefetch?` | `boolean` | If set to `true`, calling `fetchNextPage` repeatedly will invoke `queryFn` every time, whether the previous invocation has resolved or not. Also, the result from previous invocations will be ignored. If set to `false`, calling `fetchNextPage` repeatedly won't have any effect until the first invocation has resolved. Defaults to `true`. | +| `throwOnError?` | `boolean` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. Defaults to `false`, in which case failed refetches are swallowed and not surfaced to the caller. | diff --git a/docs/framework/angular/reference/interfaces/FetchPreviousPageOptions.md b/docs/framework/angular/reference/interfaces/FetchPreviousPageOptions.md index 64d31e4a063..fc45962fcf3 100644 --- a/docs/framework/angular/reference/interfaces/FetchPreviousPageOptions.md +++ b/docs/framework/angular/reference/interfaces/FetchPreviousPageOptions.md @@ -3,7 +3,7 @@ id: FetchPreviousPageOptions title: FetchPreviousPageOptions --- -Defined in: [packages/query-core/src/types.ts:809](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L809) +Defined in: packages/query-core/dist-ts/src/types.d.ts:405 ## Extends @@ -11,7 +11,7 @@ Defined in: [packages/query-core/src/types.ts:809](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `cancelRefetch?` | `boolean` | `true` | If set to `true`, calling `fetchPreviousPage` repeatedly will invoke `queryFn` every time, whether the previous invocation has resolved or not. Also, the result from previous invocations will be ignored. If set to `false`, calling `fetchPreviousPage` repeatedly won't have any effect until the first invocation has resolved. | -| `throwOnError?` | `boolean` | `false` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. If set to `false`, failed refetches are swallowed and not surfaced to the caller. | +| Property | Type | Description | +| ------ | ------ | ------ | +| `cancelRefetch?` | `boolean` | If set to `true`, calling `fetchPreviousPage` repeatedly will invoke `queryFn` every time, whether the previous invocation has resolved or not. Also, the result from previous invocations will be ignored. If set to `false`, calling `fetchPreviousPage` repeatedly won't have any effect until the first invocation has resolved. Defaults to `true`. | +| `throwOnError?` | `boolean` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. Defaults to `false`, in which case failed refetches are swallowed and not surfaced to the caller. | diff --git a/docs/framework/angular/reference/interfaces/FetchQueryOptions.md b/docs/framework/angular/reference/interfaces/FetchQueryOptions.md index 8d7aa008acb..1003d82e93c 100644 --- a/docs/framework/angular/reference/interfaces/FetchQueryOptions.md +++ b/docs/framework/angular/reference/interfaces/FetchQueryOptions.md @@ -3,7 +3,7 @@ id: FetchQueryOptions title: FetchQueryOptions --- -Defined in: [packages/query-core/src/types.ts:654](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L654) +Defined in: packages/query-core/dist-ts/src/types.d.ts:332 ## Deprecated @@ -39,21 +39,21 @@ Defined in: [packages/query-core/src/types.ts:654](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| ~~`gcTime?`~~ | `number` | `undefined` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | -| ~~`initialData?`~~ | `TData` \| () => `TData` \| `undefined` | `undefined` | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | -| ~~`initialDataUpdatedAt?`~~ | `number` \| () => `number` \| `undefined` | `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | -| ~~`initialPageParam?`~~ | `undefined` | `undefined` | - | -| ~~`maxPages?`~~ | `number` | `undefined` | Maximum number of pages to store in the data of an infinite query. | -| ~~`meta?`~~ | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | -| ~~`networkMode?`~~ | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a query is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| ~~`persister?`~~ | (`queryFn`: (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`NoInfer`\<`TQueryKey`\>, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\>, `context`: `object`, `query`: [`Query`](../classes/Query.md)) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | -| ~~`queryFn?`~~ | \| *typeof* [`skipToken`](../variables/skipToken.md) \| (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`TQueryKey`, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | -| ~~`queryHash?`~~ | `string` | `undefined` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | -| ~~`queryKey`~~ | `TQueryKey` & `object` | `undefined` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | -| ~~`queryKeyHashFn?`~~ | (`queryKey`: `TQueryKey`) => `string` | `undefined` | If specified, this function is used to hash the `queryKey` to a string. | -| ~~`retry?`~~ | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `undefined` | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | -| ~~`retryDelay?`~~ | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| ~~`staleTime?`~~ | \| `number` \| `"static"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>) => `number` \| `"static"` | `undefined` | The time in milliseconds after data is considered stale. If the data is fresh it will be returned from the cache. | -| ~~`structuralSharing?`~~ | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | `true` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. | +| Property | Type | Description | +| ------ | ------ | ------ | +| ~~`gcTime?`~~ | `number` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | +| ~~`initialData?`~~ | \| `TData` \| [`InitialDataFunction`](../type-aliases/InitialDataFunction.md)\<`TData`\> | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | +| ~~`initialDataUpdatedAt?`~~ | `number` \| () => `number` \| `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | +| ~~`initialPageParam?`~~ | `undefined` | - | +| ~~`maxPages?`~~ | `number` | Maximum number of pages to store in the data of an infinite query. | +| ~~`meta?`~~ | `Record`\<`string`, `unknown`\> | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | +| ~~`networkMode?`~~ | [`NetworkMode`](../type-aliases/NetworkMode.md) | Controls whether a query is allowed to run based on the current network connectivity. Defaults to `'online'`. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| ~~`persister?`~~ | [`QueryPersister`](../type-aliases/QueryPersister.md)\<`TQueryFnData`, `NoInfer`\<`TQueryKey`\>, `TPageParam`\> | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | +| ~~`queryFn?`~~ | \| *typeof* [`skipToken`](../variables/skipToken.md) \| [`QueryFunction`](../type-aliases/QueryFunction.md)\<`TQueryFnData`, `TQueryKey`, `TPageParam`\> | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | +| ~~`queryHash?`~~ | `string` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | +| ~~`queryKey`~~ | `TQueryKey` & `object` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | +| ~~`queryKeyHashFn?`~~ | [`QueryKeyHashFunction`](../type-aliases/QueryKeyHashFunction.md)\<`TQueryKey`\> | If specified, this function is used to hash the `queryKey` to a string. | +| ~~`retry?`~~ | `RetryValue`\<`TError`\> | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | +| ~~`retryDelay?`~~ | `RetryDelayValue`\<`TError`\> | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | +| ~~`staleTime?`~~ | [`StaleTimeFunction`](../type-aliases/StaleTimeFunction.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> | The time in milliseconds after data is considered stale. If the data is fresh it will be returned from the cache. | +| ~~`structuralSharing?`~~ | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. Defaults to `true`. | diff --git a/docs/framework/angular/reference/interfaces/FocusManager.md b/docs/framework/angular/reference/interfaces/FocusManager.md index c0e6c1dcf22..e7b524a6f24 100644 --- a/docs/framework/angular/reference/interfaces/FocusManager.md +++ b/docs/framework/angular/reference/interfaces/FocusManager.md @@ -3,7 +3,7 @@ id: FocusManager title: FocusManager --- -Defined in: [packages/query-core/src/focusManager.ts:14](https://github.com/TanStack/query/blob/main/packages/query-core/src/focusManager.ts#L14) +Defined in: packages/query-core/dist-ts/src/focusManager.d.ts:9 The `FocusManager` manages the focus state within TanStack Query. @@ -27,9 +27,7 @@ It can be used to change the default event listeners or to manually change the f hasListeners(): boolean; ``` -Defined in: [packages/query-core/src/subscribable.ts:41](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L41) - -Returns `true` while at least one listener is registered, `false` once they have all unsubscribed. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:5 #### Returns @@ -49,7 +47,7 @@ Subscribable.hasListeners isFocused(): boolean; ``` -Defined in: [packages/query-core/src/focusManager.ts:128](https://github.com/TanStack/query/blob/main/packages/query-core/src/focusManager.ts#L128) +Defined in: packages/query-core/dist-ts/src/focusManager.d.ts:66 `isFocused` can be used to get the current focus state. @@ -65,7 +63,7 @@ Defined in: [packages/query-core/src/focusManager.ts:128](https://github.com/Tan onFocus(): void; ``` -Defined in: [packages/query-core/src/focusManager.ts:118](https://github.com/TanStack/query/blob/main/packages/query-core/src/focusManager.ts#L118) +Defined in: packages/query-core/dist-ts/src/focusManager.d.ts:62 `onFocus` notifies all subscribed listeners with the current focus state. @@ -81,7 +79,7 @@ Defined in: [packages/query-core/src/focusManager.ts:118](https://github.com/Tan protected onSubscribe(): void; ``` -Defined in: [packages/query-core/src/focusManager.ts:39](https://github.com/TanStack/query/blob/main/packages/query-core/src/focusManager.ts#L39) +Defined in: packages/query-core/dist-ts/src/focusManager.d.ts:12 #### Returns @@ -101,7 +99,7 @@ Subscribable.onSubscribe protected onUnsubscribe(): void; ``` -Defined in: [packages/query-core/src/focusManager.ts:45](https://github.com/TanStack/query/blob/main/packages/query-core/src/focusManager.ts#L45) +Defined in: packages/query-core/dist-ts/src/focusManager.d.ts:13 #### Returns @@ -121,7 +119,7 @@ Subscribable.onUnsubscribe setEventListener(setup: SetupFn): void; ``` -Defined in: [packages/query-core/src/focusManager.ts:77](https://github.com/TanStack/query/blob/main/packages/query-core/src/focusManager.ts#L77) +Defined in: packages/query-core/dist-ts/src/focusManager.d.ts:39 `setEventListener` can be used to set a custom event listener that will be used to determine the focus state. The provided `setup` function @@ -166,7 +164,7 @@ focusManager.setEventListener((handleFocus) => { setFocused(focused?: boolean): void; ``` -Defined in: [packages/query-core/src/focusManager.ts:107](https://github.com/TanStack/query/blob/main/packages/query-core/src/focusManager.ts#L107) +Defined in: packages/query-core/dist-ts/src/focusManager.d.ts:58 `setFocused` can be used to manually set the focus state. Set `undefined` to fall back to the default focus check. @@ -204,11 +202,7 @@ focusManager.setFocused(undefined) subscribe(listener: Listener): () => void; ``` -Defined in: [packages/query-core/src/subscribable.ts:27](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L27) - -Registers a listener to be called on every update this object notifies about. Returns a function -that removes the listener again — call it to stop listening. The base class never drops a listener -on its own, though some subclasses clear all of theirs in `destroy()`. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:4 #### Parameters diff --git a/docs/framework/angular/reference/interfaces/HydrateOptions.md b/docs/framework/angular/reference/interfaces/HydrateOptions.md index eccc9b8b513..827c1500663 100644 --- a/docs/framework/angular/reference/interfaces/HydrateOptions.md +++ b/docs/framework/angular/reference/interfaces/HydrateOptions.md @@ -3,7 +3,7 @@ id: HydrateOptions title: HydrateOptions --- -Defined in: [packages/query-core/src/hydration.ts:61](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L61) +Defined in: packages/query-core/dist-ts/src/hydration.d.ts:28 Options for `hydrate`, controlling the default options applied to queries/mutations restored from a `DehydratedState`, and how to reverse any transformation applied by `DehydrateOptions.serializeData`. diff --git a/docs/framework/angular/reference/interfaces/InfiniteData.md b/docs/framework/angular/reference/interfaces/InfiniteData.md index c4a020f78d4..c5f09ed050a 100644 --- a/docs/framework/angular/reference/interfaces/InfiniteData.md +++ b/docs/framework/angular/reference/interfaces/InfiniteData.md @@ -3,10 +3,7 @@ id: InfiniteData title: InfiniteData --- -Defined in: [packages/query-core/src/types.ts:251](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L251) - -The data shape of an infinite query: every page fetched so far, plus the page param each one was fetched with. -`pages` and `pageParams` are index-aligned — `pageParams[i]` is the param that produced `pages[i]`. +Defined in: packages/query-core/dist-ts/src/types.d.ts:77 ## Type Parameters diff --git a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverBaseResult.md b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverBaseResult.md index 713eba1281d..b670b772251 100644 --- a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverBaseResult.md +++ b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverBaseResult.md @@ -3,7 +3,7 @@ id: InfiniteQueryObserverBaseResult title: InfiniteQueryObserverBaseResult --- -Defined in: [packages/query-core/src/types.ts:1063](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1063) +Defined in: packages/query-core/dist-ts/src/types.d.ts:613 ## Extends @@ -41,7 +41,7 @@ Defined in: [packages/query-core/src/types.ts:1063](https://github.com/TanStack/ | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | | `fetchNextPage` | (`options?`: [`FetchNextPageOptions`](FetchNextPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the next "page" of results. | | `fetchPreviousPage` | (`options?`: [`FetchPreviousPageOptions`](FetchPreviousPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the previous "page" of results. | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | | `hasNextPage` | `boolean` | Will be `true` if there is a next page to be fetched (known via the `getNextPageParam` option). | | `hasPreviousPage` | `boolean` | Will be `true` if there is a previous page to be fetched (known via the `getPreviousPageParam` option). | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | @@ -64,4 +64,4 @@ Defined in: [packages/query-core/src/types.ts:1063](https://github.com/TanStack/ | `isStale` | `boolean` | Will be `true` if the data in the cache is invalidated or if the data is older than the given `staleTime`. | | `isSuccess` | `boolean` | A derived boolean from the `status` variable, provided for convenience. - `true` if the query has received a response with no errors and is ready to display its data. | | `refetch` | (`options?`: [`RefetchOptions`](RefetchOptions.md)) => `Promise`\<[`QueryObserverResult`](../type-aliases/QueryObserverResult.md)\<`TData`, `TError`\>\> | A function to manually refetch the query. | -| `status` | `"error"` \| `"pending"` \| `"success"` | The status of the query. - Will be: - `pending` if there's no cached data and no query attempt was finished yet. - `error` if the query attempt resulted in an error. - `success` if the query has received a response with no errors and is ready to display its data. | +| `status` | [`QueryStatus`](../type-aliases/QueryStatus.md) | The status of the query. - Will be: - `pending` if there's no cached data and no query attempt was finished yet. - `error` if the query attempt resulted in an error. - `success` if the query has received a response with no errors and is ready to display its data. | diff --git a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverLoadingErrorResult.md b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverLoadingErrorResult.md index 8805f7b9498..d4359e64321 100644 --- a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverLoadingErrorResult.md +++ b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverLoadingErrorResult.md @@ -3,7 +3,7 @@ id: InfiniteQueryObserverLoadingErrorResult title: InfiniteQueryObserverLoadingErrorResult --- -Defined in: [packages/query-core/src/types.ts:1140](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1140) +Defined in: packages/query-core/dist-ts/src/types.d.ts:674 ## Extends @@ -32,7 +32,7 @@ Defined in: [packages/query-core/src/types.ts:1140](https://github.com/TanStack/ | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | | `fetchNextPage` | (`options?`: [`FetchNextPageOptions`](FetchNextPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the next "page" of results. | - | | `fetchPreviousPage` | (`options?`: [`FetchPreviousPageOptions`](FetchPreviousPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the previous "page" of results. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `hasNextPage` | `boolean` | Will be `true` if there is a next page to be fetched (known via the `getNextPageParam` option). | - | | `hasPreviousPage` | `boolean` | Will be `true` if there is a previous page to be fetched (known via the `getPreviousPageParam` option). | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | diff --git a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverLoadingResult.md b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverLoadingResult.md index bd9cfec5ed6..3602bd2ea10 100644 --- a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverLoadingResult.md +++ b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverLoadingResult.md @@ -3,7 +3,7 @@ id: InfiniteQueryObserverLoadingResult title: InfiniteQueryObserverLoadingResult --- -Defined in: [packages/query-core/src/types.ts:1122](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1122) +Defined in: packages/query-core/dist-ts/src/types.d.ts:660 ## Extends @@ -32,7 +32,7 @@ Defined in: [packages/query-core/src/types.ts:1122](https://github.com/TanStack/ | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | | `fetchNextPage` | (`options?`: [`FetchNextPageOptions`](FetchNextPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the next "page" of results. | - | | `fetchPreviousPage` | (`options?`: [`FetchPreviousPageOptions`](FetchPreviousPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the previous "page" of results. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `hasNextPage` | `boolean` | Will be `true` if there is a next page to be fetched (known via the `getNextPageParam` option). | - | | `hasPreviousPage` | `boolean` | Will be `true` if there is a previous page to be fetched (known via the `getPreviousPageParam` option). | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | diff --git a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverOptions.md b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverOptions.md index dced173fa55..58fd88ae5d8 100644 --- a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverOptions.md +++ b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverOptions.md @@ -3,7 +3,7 @@ id: InfiniteQueryObserverOptions title: InfiniteQueryObserverOptions --- -Defined in: [packages/query-core/src/types.ts:594](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L594) +Defined in: packages/query-core/dist-ts/src/types.d.ts:319 ## Extends @@ -33,35 +33,35 @@ Defined in: [packages/query-core/src/types.ts:594](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `enabled?` | \| `false` \| `true` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` | `true` | Set this to `false` or a function that returns `false` to disable automatic refetching when the query mounts or changes query keys. To refetch the query, use the `refetch` method returned from the `useQuery` instance. Accepts a boolean or function that returns a boolean. | -| `gcTime?` | `number` | `undefined` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | -| `getNextPageParam` | (`lastPage`: `TQueryFnData`, `allPages`: `TQueryFnData`[], `lastPageParam`: `TPageParam`, `allPageParams`: `TPageParam`[]) => `TPageParam` \| `null` \| `undefined` | `undefined` | This function can be set to automatically get the next cursor for infinite queries. The result will also be used to determine the value of `hasNextPage`. | -| `getPreviousPageParam?` | (`firstPage`: `TQueryFnData`, `allPages`: `TQueryFnData`[], `firstPageParam`: `TPageParam`, `allPageParams`: `TPageParam`[]) => `TPageParam` \| `null` \| `undefined` | `undefined` | This function can be set to automatically get the previous cursor for infinite queries. The result will also be used to determine the value of `hasPreviousPage`. | -| `initialData?` | \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| () => \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| `undefined` | `undefined` | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | -| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | -| `initialPageParam` | `TPageParam` | `undefined` | The page param to start from when an infinite query has no pages yet. It is passed to `queryFn` as `pageParam` for the first page; every page after that gets the value returned by `getNextPageParam` or `getPreviousPageParam`. It only applies while the query has no pages: once a first page exists, refetching starts from that page's own param instead. | -| `maxPages?` | `number` | `undefined` | Maximum number of pages to store in the data of an infinite query. | -| `meta?` | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | -| `networkMode?` | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a query is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| `notifyOnChangeProps?` | \| ( \| `"error"` \| `"data"` \| `"isError"` \| `"isPending"` \| `"isLoading"` \| `"isLoadingError"` \| `"isRefetchError"` \| `"isSuccess"` \| `"isPlaceholderData"` \| `"status"` \| `"dataUpdatedAt"` \| `"errorUpdatedAt"` \| `"failureCount"` \| `"failureReason"` \| `"errorUpdateCount"` \| `"isFetched"` \| `"isFetchedAfterMount"` \| `"isFetching"` \| `"isInitialLoading"` \| `"isPaused"` \| `"isRefetching"` \| `"isStale"` \| `"isEnabled"` \| `"refetch"` \| `"fetchStatus"` \| `"fetchNextPage"` \| `"fetchPreviousPage"` \| `"hasNextPage"` \| `"hasPreviousPage"` \| `"isFetchNextPageError"` \| `"isFetchingNextPage"` \| `"isFetchPreviousPageError"` \| `"isFetchingPreviousPage"`)[] \| `"all"` \| () => \| `"all"` \| ( \| `"error"` \| `"data"` \| `"isError"` \| `"isPending"` \| `"isLoading"` \| `"isLoadingError"` \| `"isRefetchError"` \| `"isSuccess"` \| `"isPlaceholderData"` \| `"status"` \| `"dataUpdatedAt"` \| `"errorUpdatedAt"` \| `"failureCount"` \| `"failureReason"` \| `"errorUpdateCount"` \| `"isFetched"` \| `"isFetchedAfterMount"` \| `"isFetching"` \| `"isInitialLoading"` \| `"isPaused"` \| `"isRefetching"` \| `"isStale"` \| `"isEnabled"` \| `"refetch"` \| `"fetchStatus"` \| `"fetchNextPage"` \| `"fetchPreviousPage"` \| `"hasNextPage"` \| `"hasPreviousPage"` \| `"isFetchNextPageError"` \| `"isFetchingNextPage"` \| `"isFetchPreviousPageError"` \| `"isFetchingPreviousPage"`)[] \| `undefined` | `undefined` | If set, the component will only re-render if any of the listed properties change. When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change. When set to `'all'`, the component will re-render whenever a query is updated. When set to a function, the function will be executed to compute the list of properties. Defaults to `undefined`, in which case property access is tracked automatically, and the component only re-renders when one of the tracked properties changes. | -| `persister?` | (`queryFn`: (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`NoInfer`\<`TQueryKey`\>, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\>, `context`: `object`, `query`: [`Query`](../classes/Query.md)) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | -| `placeholderData?` | \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| (`previousData`: \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| `undefined`, `previousQuery`: \| [`Query`](../classes/Query.md)\<[`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\> \| `undefined`) => \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| `undefined` | `undefined` | If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `loading` data and no initialData has been provided. | -| `queryFn?` | \| *typeof* [`skipToken`](../variables/skipToken.md) \| (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`TQueryKey`, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | -| `queryHash?` | `string` | `undefined` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | -| `queryKey` | `TQueryKey` & `object` | `undefined` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | -| `queryKeyHashFn?` | (`queryKey`: `TQueryKey`) => `string` | `undefined` | If specified, this function is used to hash the `queryKey` to a string. | -| `refetchInterval?` | \| `number` \| `false` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `number` \| `false` \| `undefined` | `false` | If set to a number, the query will continuously refetch at this frequency in milliseconds. If set to a function, the function will be executed with the latest data and query to compute a frequency | -| `refetchIntervalInBackground?` | `boolean` | `false` | If set to `true`, the query will continue to refetch while their tab/window is in the background. | -| `refetchOnMount?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | `true` | If set to `true`, the query will refetch on mount if the data is stale. If set to `false`, will disable additional instances of a query to trigger background refetch. If set to `'always'`, the query will always refetch on mount (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value | -| `refetchOnReconnect?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | `undefined` | If set to `true`, the query will refetch on reconnect if the data is stale. If set to `false`, the query will not refetch on reconnect. If set to `'always'`, the query will always refetch on reconnect (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. Defaults to `true` unless `networkMode` is `'always'`. | -| `refetchOnWindowFocus?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | `true` | If set to `true`, the query will refetch on window focus if the data is stale. If set to `false`, the query will not refetch on window focus. If set to `'always'`, the query will always refetch on window focus (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. | -| `retry?` | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `undefined` | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | -| `retryDelay?` | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| `retryOnMount?` | \| `false` \| `true` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` | `true` | If set to `false`, the query will not be retried on mount if it contains an error. If set to a function, the function will be executed with the query to compute the value. | -| `select?` | (`data`: [`InfiniteData`](InfiniteData.md)) => `TData` | `undefined` | This option can be used to transform or select a part of the data returned by the query function. It affects the returned `data` value, but does not affect what gets stored in the query cache. The `select` function will only run if `data` changed, or if the reference to the `select` function itself changes. To optimize, memoize the function so its reference stays stable across calls. | -| `staleTime?` | \| `number` \| `"static"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `number` \| `"static"` | `0` | The time in milliseconds after data is considered stale. If set to `Infinity`, the data will never be considered stale. If set to `'static'`, the data will never be considered stale. If set to a function, the function will be executed with the query to compute a `staleTime`. | -| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | `true` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. | -| `suspense?` | `boolean` | `false` | If set to `true`, the query will suspend when `status === 'pending'` and throw errors when `status === 'error'`. | -| `throwOnError?` | \| `false` \| `true` \| (`error`: `TError`, `query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` | `false` | Whether errors should be thrown instead of setting the `error` property. If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary. If set to `false` and `suspense` is `false`, errors are returned as state. If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`). | +| Property | Type | Description | +| ------ | ------ | ------ | +| `enabled?` | [`QueryBooleanOption`](../type-aliases/QueryBooleanOption.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\> | Set this to `false` or a function that returns `false` to disable automatic refetching when the query mounts or changes query keys. To refetch the query, use the `refetch` method returned from the `useQuery` instance. Accepts a boolean or function that returns a boolean. Defaults to `true`. | +| `gcTime?` | `number` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | +| `getNextPageParam` | [`GetNextPageParamFunction`](../type-aliases/GetNextPageParamFunction.md)\<`TPageParam`, `TQueryFnData`\> | This function can be set to automatically get the next cursor for infinite queries. The result will also be used to determine the value of `hasNextPage`. | +| `getPreviousPageParam?` | [`GetPreviousPageParamFunction`](../type-aliases/GetPreviousPageParamFunction.md)\<`TPageParam`, `TQueryFnData`\> | This function can be set to automatically get the previous cursor for infinite queries. The result will also be used to determine the value of `hasPreviousPage`. | +| `initialData?` | \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| [`InitialDataFunction`](../type-aliases/InitialDataFunction.md)\<[`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>\> | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | +| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | +| `initialPageParam` | `TPageParam` | - | +| `maxPages?` | `number` | Maximum number of pages to store in the data of an infinite query. | +| `meta?` | `Record`\<`string`, `unknown`\> | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | +| `networkMode?` | [`NetworkMode`](../type-aliases/NetworkMode.md) | Controls whether a query is allowed to run based on the current network connectivity. Defaults to `'online'`. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| `notifyOnChangeProps?` | [`NotifyOnChangeProps`](../type-aliases/NotifyOnChangeProps.md) | If set, the component will only re-render if any of the listed properties change. When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change. When set to `'all'`, the component will re-render whenever a query is updated. When set to a function, the function will be executed to compute the list of properties. Defaults to `undefined`, in which case property access is tracked automatically, and the component only re-renders when one of the tracked properties changes. | +| `persister?` | [`QueryPersister`](../type-aliases/QueryPersister.md)\<`TQueryFnData`, `NoInfer`\<`TQueryKey`\>, `TPageParam`\> | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | +| `placeholderData?` | \| [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\> \| [`PlaceholderDataFunction`](../type-aliases/PlaceholderDataFunction.md)\<[`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\> | If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `loading` data and no initialData has been provided. | +| `queryFn?` | \| *typeof* [`skipToken`](../variables/skipToken.md) \| [`QueryFunction`](../type-aliases/QueryFunction.md)\<`TQueryFnData`, `TQueryKey`, `TPageParam`\> | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | +| `queryHash?` | `string` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | +| `queryKey` | `TQueryKey` & `object` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | +| `queryKeyHashFn?` | [`QueryKeyHashFunction`](../type-aliases/QueryKeyHashFunction.md)\<`TQueryKey`\> | If specified, this function is used to hash the `queryKey` to a string. | +| `refetchInterval?` | \| `number` \| `false` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `number` \| `false` \| `undefined` | If set to a number, the query will continuously refetch at this frequency in milliseconds. If set to a function, the function will be executed with the latest data and query to compute a frequency Defaults to `false`. | +| `refetchIntervalInBackground?` | `boolean` | If set to `true`, the query will continue to refetch while their tab/window is in the background. Defaults to `false`. | +| `refetchOnMount?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | If set to `true`, the query will refetch on mount if the data is stale. If set to `false`, will disable additional instances of a query to trigger background refetch. If set to `'always'`, the query will always refetch on mount (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value Defaults to `true`. | +| `refetchOnReconnect?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | If set to `true`, the query will refetch on reconnect if the data is stale. If set to `false`, the query will not refetch on reconnect. If set to `'always'`, the query will always refetch on reconnect (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. Defaults to `true` unless `networkMode` is `'always'`. | +| `refetchOnWindowFocus?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\>) => `boolean` \| `"always"` | If set to `true`, the query will refetch on window focus if the data is stale. If set to `false`, the query will not refetch on window focus. If set to `'always'`, the query will always refetch on window focus (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. Defaults to `true`. | +| `retry?` | `RetryValue`\<`TError`\> | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | +| `retryDelay?` | `RetryDelayValue`\<`TError`\> | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | +| `retryOnMount?` | [`QueryBooleanOption`](../type-aliases/QueryBooleanOption.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\> | If set to `false`, the query will not be retried on mount if it contains an error. If set to a function, the function will be executed with the query to compute the value. Defaults to `true`. | +| `select?` | (`data`: [`InfiniteData`](InfiniteData.md)) => `TData` | This option can be used to transform or select a part of the data returned by the query function. It affects the returned `data` value, but does not affect what gets stored in the query cache. The `select` function will only run if `data` changed, or if the reference to the `select` function itself changes. To optimize, memoize the function so its reference stays stable across calls. | +| `staleTime?` | [`StaleTimeFunction`](../type-aliases/StaleTimeFunction.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\> | The time in milliseconds after data is considered stale. If set to `Infinity`, the data will never be considered stale. If set to `'static'`, the data will never be considered stale. If set to a function, the function will be executed with the query to compute a `staleTime`. Defaults to `0`. | +| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. Defaults to `true`. | +| `suspense?` | `boolean` | If set to `true`, the query will suspend when `status === 'pending'` and throw errors when `status === 'error'`. Defaults to `false`. | +| `throwOnError?` | [`ThrowOnError`](../type-aliases/ThrowOnError.md)\<`TQueryFnData`, `TError`, [`InfiniteData`](InfiniteData.md)\<`TQueryFnData`, `TPageParam`\>, `TQueryKey`\> | Whether errors should be thrown instead of setting the `error` property. If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary. If set to `false` and `suspense` is `false`, errors are returned as state. If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`). Defaults to `false`. | diff --git a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverPendingResult.md b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverPendingResult.md index 4997bcce9f7..cbee9167612 100644 --- a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverPendingResult.md +++ b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverPendingResult.md @@ -3,7 +3,7 @@ id: InfiniteQueryObserverPendingResult title: InfiniteQueryObserverPendingResult --- -Defined in: [packages/query-core/src/types.ts:1105](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1105) +Defined in: packages/query-core/dist-ts/src/types.d.ts:647 ## Extends @@ -32,7 +32,7 @@ Defined in: [packages/query-core/src/types.ts:1105](https://github.com/TanStack/ | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | | `fetchNextPage` | (`options?`: [`FetchNextPageOptions`](FetchNextPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the next "page" of results. | - | | `fetchPreviousPage` | (`options?`: [`FetchPreviousPageOptions`](FetchPreviousPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the previous "page" of results. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `hasNextPage` | `boolean` | Will be `true` if there is a next page to be fetched (known via the `getNextPageParam` option). | - | | `hasPreviousPage` | `boolean` | Will be `true` if there is a previous page to be fetched (known via the `getPreviousPageParam` option). | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | diff --git a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverPlaceholderResult.md b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverPlaceholderResult.md index 5dba2fcd974..e01f2386f28 100644 --- a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverPlaceholderResult.md +++ b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverPlaceholderResult.md @@ -3,7 +3,7 @@ id: InfiniteQueryObserverPlaceholderResult title: InfiniteQueryObserverPlaceholderResult --- -Defined in: [packages/query-core/src/types.ts:1192](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1192) +Defined in: packages/query-core/dist-ts/src/types.d.ts:714 ## Extends @@ -32,7 +32,7 @@ Defined in: [packages/query-core/src/types.ts:1192](https://github.com/TanStack/ | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | | `fetchNextPage` | (`options?`: [`FetchNextPageOptions`](FetchNextPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the next "page" of results. | - | | `fetchPreviousPage` | (`options?`: [`FetchPreviousPageOptions`](FetchPreviousPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the previous "page" of results. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `hasNextPage` | `boolean` | Will be `true` if there is a next page to be fetched (known via the `getNextPageParam` option). | - | | `hasPreviousPage` | `boolean` | Will be `true` if there is a previous page to be fetched (known via the `getPreviousPageParam` option). | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | diff --git a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverRefetchErrorResult.md b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverRefetchErrorResult.md index 0781aacb4da..6d700070874 100644 --- a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverRefetchErrorResult.md +++ b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverRefetchErrorResult.md @@ -3,7 +3,7 @@ id: InfiniteQueryObserverRefetchErrorResult title: InfiniteQueryObserverRefetchErrorResult --- -Defined in: [packages/query-core/src/types.ts:1158](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1158) +Defined in: packages/query-core/dist-ts/src/types.d.ts:688 ## Extends @@ -32,7 +32,7 @@ Defined in: [packages/query-core/src/types.ts:1158](https://github.com/TanStack/ | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | | `fetchNextPage` | (`options?`: [`FetchNextPageOptions`](FetchNextPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the next "page" of results. | - | | `fetchPreviousPage` | (`options?`: [`FetchPreviousPageOptions`](FetchPreviousPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the previous "page" of results. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `hasNextPage` | `boolean` | Will be `true` if there is a next page to be fetched (known via the `getNextPageParam` option). | - | | `hasPreviousPage` | `boolean` | Will be `true` if there is a previous page to be fetched (known via the `getPreviousPageParam` option). | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | diff --git a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverSuccessResult.md b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverSuccessResult.md index 3c1302ed363..176fd96de3b 100644 --- a/docs/framework/angular/reference/interfaces/InfiniteQueryObserverSuccessResult.md +++ b/docs/framework/angular/reference/interfaces/InfiniteQueryObserverSuccessResult.md @@ -3,7 +3,7 @@ id: InfiniteQueryObserverSuccessResult title: InfiniteQueryObserverSuccessResult --- -Defined in: [packages/query-core/src/types.ts:1174](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1174) +Defined in: packages/query-core/dist-ts/src/types.d.ts:700 ## Extends @@ -32,7 +32,7 @@ Defined in: [packages/query-core/src/types.ts:1174](https://github.com/TanStack/ | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | | `fetchNextPage` | (`options?`: [`FetchNextPageOptions`](FetchNextPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the next "page" of results. | - | | `fetchPreviousPage` | (`options?`: [`FetchPreviousPageOptions`](FetchPreviousPageOptions.md)) => `Promise`\<[`InfiniteQueryObserverResult`](../type-aliases/InfiniteQueryObserverResult.md)\<`TData`, `TError`\>\> | This function allows you to fetch the previous "page" of results. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `hasNextPage` | `boolean` | Will be `true` if there is a next page to be fetched (known via the `getNextPageParam` option). | - | | `hasPreviousPage` | `boolean` | Will be `true` if there is a previous page to be fetched (known via the `getPreviousPageParam` option). | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | diff --git a/docs/framework/angular/reference/interfaces/InfiniteQueryPageParamsOptions.md b/docs/framework/angular/reference/interfaces/InfiniteQueryPageParamsOptions.md index 58bc7bb37b8..698d1f4fba0 100644 --- a/docs/framework/angular/reference/interfaces/InfiniteQueryPageParamsOptions.md +++ b/docs/framework/angular/reference/interfaces/InfiniteQueryPageParamsOptions.md @@ -3,7 +3,7 @@ id: InfiniteQueryPageParamsOptions title: InfiniteQueryPageParamsOptions --- -Defined in: [packages/query-core/src/types.ts:406](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L406) +Defined in: packages/query-core/dist-ts/src/types.d.ts:197 ## Extends @@ -27,6 +27,6 @@ Defined in: [packages/query-core/src/types.ts:406](https://github.com/TanStack/q | Property | Type | Description | | ------ | ------ | ------ | -| `getNextPageParam` | (`lastPage`: `TQueryFnData`, `allPages`: `TQueryFnData`[], `lastPageParam`: `TPageParam`, `allPageParams`: `TPageParam`[]) => `TPageParam` \| `null` \| `undefined` | This function can be set to automatically get the next cursor for infinite queries. The result will also be used to determine the value of `hasNextPage`. | -| `getPreviousPageParam?` | (`firstPage`: `TQueryFnData`, `allPages`: `TQueryFnData`[], `firstPageParam`: `TPageParam`, `allPageParams`: `TPageParam`[]) => `TPageParam` \| `null` \| `undefined` | This function can be set to automatically get the previous cursor for infinite queries. The result will also be used to determine the value of `hasPreviousPage`. | -| `initialPageParam` | `TPageParam` | The page param to start from when an infinite query has no pages yet. It is passed to `queryFn` as `pageParam` for the first page; every page after that gets the value returned by `getNextPageParam` or `getPreviousPageParam`. It only applies while the query has no pages: once a first page exists, refetching starts from that page's own param instead. | +| `getNextPageParam` | [`GetNextPageParamFunction`](../type-aliases/GetNextPageParamFunction.md)\<`TPageParam`, `TQueryFnData`\> | This function can be set to automatically get the next cursor for infinite queries. The result will also be used to determine the value of `hasNextPage`. | +| `getPreviousPageParam?` | [`GetPreviousPageParamFunction`](../type-aliases/GetPreviousPageParamFunction.md)\<`TPageParam`, `TQueryFnData`\> | This function can be set to automatically get the previous cursor for infinite queries. The result will also be used to determine the value of `hasPreviousPage`. | +| `initialPageParam` | `TPageParam` | - | diff --git a/docs/framework/angular/reference/interfaces/InitialPageParam.md b/docs/framework/angular/reference/interfaces/InitialPageParam.md index cbab0471251..acc8b34f297 100644 --- a/docs/framework/angular/reference/interfaces/InitialPageParam.md +++ b/docs/framework/angular/reference/interfaces/InitialPageParam.md @@ -3,7 +3,7 @@ id: InitialPageParam title: InitialPageParam --- -Defined in: [packages/query-core/src/types.ts:395](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L395) +Defined in: packages/query-core/dist-ts/src/types.d.ts:194 ## Extended by @@ -17,6 +17,6 @@ Defined in: [packages/query-core/src/types.ts:395](https://github.com/TanStack/q ## Properties -| Property | Type | Description | -| ------ | ------ | ------ | -| `initialPageParam` | `TPageParam` | The page param to start from when an infinite query has no pages yet. It is passed to `queryFn` as `pageParam` for the first page; every page after that gets the value returned by `getNextPageParam` or `getPreviousPageParam`. It only applies while the query has no pages: once a first page exists, refetching starts from that page's own param instead. | +| Property | Type | +| ------ | ------ | +| `initialPageParam` | `TPageParam` | diff --git a/docs/framework/angular/reference/interfaces/InjectQueriesOptions.md b/docs/framework/angular/reference/interfaces/InjectQueriesOptions.md index cf774321bac..05e3b805ceb 100644 --- a/docs/framework/angular/reference/interfaces/InjectQueriesOptions.md +++ b/docs/framework/angular/reference/interfaces/InjectQueriesOptions.md @@ -17,32 +17,7 @@ Defined in: [packages/angular-query/src/inject-queries.types.ts:213](https://git ## Properties -### combine()? - -```ts -optional combine: (result) => TCombinedResult; -``` - -Defined in: [packages/angular-query/src/inject-queries.types.ts:222](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-queries.types.ts#L222) - -#### Parameters - -##### result - -`T` *extends* \[\] ? \[\] : `T` *extends* \[`Head`\] ? \[`GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<`Head`\>\[`"data"`\], `QueryObserverResult`\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>, `DefinedQueryObserverResult`\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>\>\] : `T` *extends* \[`Head`, `...Tails[]`\] ? \[`...Tails[]`\] *extends* \[\] ? \[\] : \[`...Tails[]`\] *extends* \[`Head`\] ? \[`GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<...\>\[`"data"`\], `QueryObserverResult`\<...\[...\], ...\[...\]\>, `DefinedQueryObserverResult`\<...\[...\], ...\[...\]\>\>, `GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<...\>\[`"data"`\], `QueryObserverResult`\<...\[...\], ...\[...\]\>, `DefinedQueryObserverResult`\<...\[...\], ...\[...\]\>\>\] : \[`...Tails[]`\] *extends* \[`Head`, `...Tails[]`\] ? \[`...Tails[]`\] *extends* \[\] ? \[\] : \[`...(...)[]`\] *extends* \[...\] ? \[..., ..., ...\] : ... *extends* ... ? ... : ... : \[...\{ \[K in (...) \| (...) \| (...)\]: GenericGetDefinedOrUndefinedQueryResult\<(...), (...), (...), (...)\> \}\[\]\] : \{ \[K in string \| number \| symbol\]: GenericGetDefinedOrUndefinedQueryResult\\], InferDataAndError\\]\>\["data"\], QueryObserverResult\\["data"\], InferDataAndError\<(...)\[(...)\]\>\["error"\]\>, DefinedQueryObserverResult\\["data"\], InferDataAndError\<(...)\[(...)\]\>\["error"\]\>\> \} - -#### Returns - -`TCombinedResult` - -*** - -### queries - -```ts -queries: - | readonly [{ [K in string | number | symbol]: GetCreateQueryOptionsForCreateQueries]> }] - | readonly [T extends [] ? [] : T extends [Head] ? [GetCreateQueryOptionsForCreateQueries] : T extends [Head, ...Tails[]] ? [...Tails[]] extends [] ? [] : [...Tails[]] extends [Head] ? [GetCreateQueryOptionsForCreateQueries, GetCreateQueryOptionsForCreateQueries] : [...Tails[]] extends [Head, ...Tails[]] ? [...Tails[]] extends [] ? [] : [...(...)[]] extends [...] ? [..., ..., ...] : ... extends ... ? ... : ... : readonly unknown[] extends [...Tails[]] ? [...Tails[]] : [...(...)[]] extends ...[] ? ...[] : ...[] : readonly unknown[] extends T ? T : T extends QueryObserverOptionsForCreateQueries[] ? QueryObserverOptionsForCreateQueries[] : QueryObserverOptionsForCreateQueries[]]; -``` - -Defined in: [packages/angular-query/src/inject-queries.types.ts:217](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-queries.types.ts#L217) +| Property | Type | +| ------ | ------ | +| `combine?` | (`result`: `T` *extends* \[\] ? \[\] : `T` *extends* \[`Head`\] ? \[`GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<`Head`\>\[`"data"`\], [`QueryObserverResult`](../type-aliases/QueryObserverResult.md)\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>, [`DefinedQueryObserverResult`](../type-aliases/DefinedQueryObserverResult.md)\<`InferDataAndError`\<`Head`\>\[`"data"`\], `InferDataAndError`\<`Head`\>\[`"error"`\]\>\>\] : `T` *extends* \[`Head`, `...Tails[]`\] ? \[`...Tails[]`\] *extends* \[\] ? \[\] : \[`...Tails[]`\] *extends* \[`Head`\] ? \[`GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<...\>\[`"data"`\], [`QueryObserverResult`](../type-aliases/QueryObserverResult.md)\<...\[...\], ...\[...\]\>, [`DefinedQueryObserverResult`](../type-aliases/DefinedQueryObserverResult.md)\<...\[...\], ...\[...\]\>\>, `GenericGetDefinedOrUndefinedQueryResult`\<`Head`, `InferDataAndError`\<...\>\[`"data"`\], [`QueryObserverResult`](../type-aliases/QueryObserverResult.md)\<...\[...\], ...\[...\]\>, [`DefinedQueryObserverResult`](../type-aliases/DefinedQueryObserverResult.md)\<...\[...\], ...\[...\]\>\>\] : \[`...Tails[]`\] *extends* \[`Head`, `...Tails[]`\] ? \[`...Tails[]`\] *extends* \[\] ? \[\] : \[`...(...)[]`\] *extends* \[...\] ? \[..., ..., ...\] : ... *extends* ... ? ... : ... : \[...\{ \[K in (...) \| (...) \| (...)\]: GenericGetDefinedOrUndefinedQueryResult\<(...), (...), (...), (...)\> \}\[\]\] : \{ \[K in string \| number \| symbol\]: GenericGetDefinedOrUndefinedQueryResult\\], InferDataAndError\\]\>\["data"\], QueryObserverResult\\["data"\], InferDataAndError\<(...)\[(...)\]\>\["error"\]\>, DefinedQueryObserverResult\\["data"\], InferDataAndError\<(...)\[(...)\]\>\["error"\]\>\> \}) => `TCombinedResult` | +| `queries` | \| readonly \[\{ \[K in string \| number \| symbol\]: GetCreateQueryOptionsForCreateQueries\\]\> \}\] \| readonly \[`T` *extends* \[\] ? \[\] : `T` *extends* \[`Head`\] ? \[`GetCreateQueryOptionsForCreateQueries`\<`Head`\>\] : `T` *extends* \[`Head`, `...Tails[]`\] ? \[`...Tails[]`\] *extends* \[\] ? \[\] : \[`...Tails[]`\] *extends* \[`Head`\] ? \[`GetCreateQueryOptionsForCreateQueries`\<`Head`\>, `GetCreateQueryOptionsForCreateQueries`\<`Head`\>\] : \[`...Tails[]`\] *extends* \[`Head`, `...Tails[]`\] ? \[`...Tails[]`\] *extends* \[\] ? \[\] : \[`...(...)[]`\] *extends* \[...\] ? \[..., ..., ...\] : ... *extends* ... ? ... : ... : readonly `unknown`[] *extends* \[`...Tails[]`\] ? \[`...Tails[]`\] : \[`...(...)[]`\] *extends* ...[] ? ...[] : ...[] : readonly `unknown`[] *extends* `T` ? `T` : `T` *extends* `QueryObserverOptionsForCreateQueries`\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>[] ? `QueryObserverOptionsForCreateQueries`\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>[] : `QueryObserverOptionsForCreateQueries`\<`unknown`, `Error`, `unknown`, readonly `unknown`[]\>[]\] | diff --git a/docs/framework/angular/reference/interfaces/InvalidateOptions.md b/docs/framework/angular/reference/interfaces/InvalidateOptions.md index 42a7f4c099e..bf22a96d45f 100644 --- a/docs/framework/angular/reference/interfaces/InvalidateOptions.md +++ b/docs/framework/angular/reference/interfaces/InvalidateOptions.md @@ -3,7 +3,7 @@ id: InvalidateOptions title: InvalidateOptions --- -Defined in: [packages/query-core/src/types.ts:794](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L794) +Defined in: packages/query-core/dist-ts/src/types.d.ts:390 ## Extends @@ -11,7 +11,7 @@ Defined in: [packages/query-core/src/types.ts:794](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `cancelRefetch?` | `boolean` | `true` | If set to `true`, a currently running request will be cancelled before a new request is made If set to `false`, no refetch will be made if there is already a request running. | -| `throwOnError?` | `boolean` | `false` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. If set to `false`, failed refetches are swallowed and not surfaced to the caller. | +| Property | Type | Description | +| ------ | ------ | ------ | +| `cancelRefetch?` | `boolean` | If set to `true`, a currently running request will be cancelled before a new request is made If set to `false`, no refetch will be made if there is already a request running. Defaults to `true`. | +| `throwOnError?` | `boolean` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. Defaults to `false`, in which case failed refetches are swallowed and not surfaced to the caller. | diff --git a/docs/framework/angular/reference/interfaces/InvalidateQueryFilters.md b/docs/framework/angular/reference/interfaces/InvalidateQueryFilters.md index 2b90939ea2b..9f4dc62ddd1 100644 --- a/docs/framework/angular/reference/interfaces/InvalidateQueryFilters.md +++ b/docs/framework/angular/reference/interfaces/InvalidateQueryFilters.md @@ -3,7 +3,7 @@ id: InvalidateQueryFilters title: InvalidateQueryFilters --- -Defined in: [packages/query-core/src/types.ts:774](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L774) +Defined in: packages/query-core/dist-ts/src/types.d.ts:376 Filters used to select queries, for example in `queryClient.getQueriesData` or `queryClient.invalidateQueries`. All provided filters must match; filters that are left unspecified are ignored. @@ -20,12 +20,12 @@ All provided filters must match; filters that are left unspecified are ignored. ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `exact?` | `boolean` | `undefined` | Match query key exactly | -| `fetchStatus?` | `"fetching"` \| `"paused"` \| `"idle"` | `undefined` | Include queries matching their fetchStatus | -| `predicate?` | (`query`: [`Query`](../classes/Query.md)) => `boolean` | `undefined` | Include queries matching this predicate function | -| `queryKey?` | `TQueryKey` \| `TuplePrefixes`\<`TQueryKey`\> | `undefined` | Include queries matching this query key | -| `refetchType?` | `QueryTypeFilter` \| `"none"` | `'active'` | Controls which of the matched (now-invalidated) queries are refetched in the background. - `'active'`: only queries with at least one active observer are refetched. - `'inactive'`: only queries with no active observer are refetched. - `'all'`: every matched query is refetched, active or not. - `'none'`: no query is refetched; matched queries are only marked as invalidated. | -| `stale?` | `boolean` | `undefined` | Include or exclude stale queries | -| `type?` | `QueryTypeFilter` | `'all'` | Filter to active queries, inactive queries or all queries | +| Property | Type | Description | +| ------ | ------ | ------ | +| `exact?` | `boolean` | Match query key exactly | +| `fetchStatus?` | [`FetchStatus`](../type-aliases/FetchStatus.md) | Include queries matching their fetchStatus | +| `predicate?` | (`query`: [`Query`](../classes/Query.md)) => `boolean` | Include queries matching this predicate function | +| `queryKey?` | `TQueryKey` \| `TuplePrefixes`\<`TQueryKey`\> | Include queries matching this query key | +| `refetchType?` | `QueryTypeFilter` \| `"none"` | Controls which of the matched (now-invalidated) queries are refetched in the background. Defaults to `'active'`. - `'active'`: only queries with at least one active observer are refetched. - `'inactive'`: only queries with no active observer are refetched. - `'all'`: every matched query is refetched, active or not. - `'none'`: no query is refetched; matched queries are only marked as invalidated. | +| `stale?` | `boolean` | Include or exclude stale queries | +| `type?` | `QueryTypeFilter` | Filter to active queries, inactive queries or all queries Defaults to `'all'`. | diff --git a/docs/framework/angular/reference/interfaces/MutateOptions.md b/docs/framework/angular/reference/interfaces/MutateOptions.md index 639203faad7..1fa8ce6f62a 100644 --- a/docs/framework/angular/reference/interfaces/MutateOptions.md +++ b/docs/framework/angular/reference/interfaces/MutateOptions.md @@ -3,7 +3,7 @@ id: MutateOptions title: MutateOptions --- -Defined in: [packages/query-core/src/types.ts:1404](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1404) +Defined in: packages/query-core/dist-ts/src/types.d.ts:799 ## Type Parameters diff --git a/docs/framework/angular/reference/interfaces/MutationCacheConfig.md b/docs/framework/angular/reference/interfaces/MutationCacheConfig.md index 5bf99e108f5..5b8cbd23631 100644 --- a/docs/framework/angular/reference/interfaces/MutationCacheConfig.md +++ b/docs/framework/angular/reference/interfaces/MutationCacheConfig.md @@ -3,7 +3,7 @@ id: MutationCacheConfig title: MutationCacheConfig --- -Defined in: [packages/query-core/src/mutationCache.ts:26](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationCache.ts#L26) +Defined in: packages/query-core/dist-ts/src/mutationCache.d.ts:16 Global callbacks that fire for every mutation handled by a `MutationCache`, regardless of which component or observer triggered it. They differ from the `defaultOptions` provided to a diff --git a/docs/framework/angular/reference/interfaces/MutationFilters.md b/docs/framework/angular/reference/interfaces/MutationFilters.md index 5e760a7a543..16a9be5df60 100644 --- a/docs/framework/angular/reference/interfaces/MutationFilters.md +++ b/docs/framework/angular/reference/interfaces/MutationFilters.md @@ -3,7 +3,7 @@ id: MutationFilters title: MutationFilters --- -Defined in: [packages/query-core/src/utils.ts:64](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L64) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:45 Filters used to select mutations, for example in `mutationCache.findAll` or `queryClient.isMutating`. All provided filters must match; filters that are left unspecified are ignored. @@ -33,4 +33,4 @@ All provided filters must match; filters that are left unspecified are ignored. | `exact?` | `boolean` | Match mutation key exactly | | `mutationKey?` | readonly `unknown`[] | Include mutations matching this mutation key | | `predicate?` | (`mutation`: [`Mutation`](../classes/Mutation.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>) => `boolean` | Include mutations matching this predicate function | -| `status?` | `"error"` \| `"pending"` \| `"success"` \| `"idle"` | Filter by mutation status | +| `status?` | [`MutationStatus`](../type-aliases/MutationStatus.md) | Filter by mutation status | diff --git a/docs/framework/angular/reference/interfaces/MutationObserverBaseResult.md b/docs/framework/angular/reference/interfaces/MutationObserverBaseResult.md index 742c15bee7d..a1a1aff2513 100644 --- a/docs/framework/angular/reference/interfaces/MutationObserverBaseResult.md +++ b/docs/framework/angular/reference/interfaces/MutationObserverBaseResult.md @@ -3,7 +3,7 @@ id: MutationObserverBaseResult title: MutationObserverBaseResult --- -Defined in: [packages/query-core/src/types.ts:1455](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1455) +Defined in: packages/query-core/dist-ts/src/types.d.ts:812 The raw state stored on a `Mutation` instance. This is the underlying state that observer results (e.g. `MutationObserverResult`) are derived from. @@ -53,6 +53,6 @@ that observer results (e.g. `MutationObserverResult`) are derived from. | `isSuccess` | `boolean` | A boolean variable derived from `status`. - `true` if the last mutation attempt was successful. | - | | `mutate` | [`MutateFunction`](../type-aliases/MutateFunction.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\> | The mutation function you can call with variables to trigger the mutation and optionally hooks on additional callback options. **Param** The variables object to pass to the `mutationFn`. **Param** This function will fire when the mutation is successful and will be passed the mutation's result. **Param** This function will fire if the mutation encounters an error and will be passed the error. **Param** This function will fire when the mutation is either successfully fetched or encounters an error and be passed either the data or error. **Remarks** - If you make multiple requests, `onSuccess` will fire only after the latest call you've made. - All the callback functions (`onSuccess`, `onError`, `onSettled`) are void functions, and the returned value will be ignored. | - | | `reset` | () => `void` | A function to clean the mutation internal state (i.e., it resets the mutation to its initial state). | - | -| `status` | `"error"` \| `"pending"` \| `"success"` \| `"idle"` | The status of the mutation. - Will be: - `idle` initial status prior to the mutation function executing. - `pending` if the mutation is currently executing. - `error` if the last mutation attempt resulted in an error. - `success` if the last mutation attempt was successful. | [`MutationState`](MutationState.md).[`status`](MutationState.md#status) | +| `status` | [`MutationStatus`](../type-aliases/MutationStatus.md) | The status of the mutation. - Will be: - `idle` initial status prior to the mutation function executing. - `pending` if the mutation is currently executing. - `error` if the last mutation attempt resulted in an error. - `success` if the last mutation attempt was successful. | [`MutationState`](MutationState.md).[`status`](MutationState.md#status) | | `submittedAt` | `number` | The timestamp for when the mutation was submitted. | - | | `variables` | `TVariables` \| `undefined` | The variables object passed to the `mutationFn`. | [`MutationState`](MutationState.md).[`variables`](MutationState.md#variables) | diff --git a/docs/framework/angular/reference/interfaces/MutationObserverErrorResult.md b/docs/framework/angular/reference/interfaces/MutationObserverErrorResult.md index 01782345a8a..29cb86db4e6 100644 --- a/docs/framework/angular/reference/interfaces/MutationObserverErrorResult.md +++ b/docs/framework/angular/reference/interfaces/MutationObserverErrorResult.md @@ -3,7 +3,7 @@ id: MutationObserverErrorResult title: MutationObserverErrorResult --- -Defined in: [packages/query-core/src/types.ts:1562](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1562) +Defined in: packages/query-core/dist-ts/src/types.d.ts:891 The raw state stored on a `Mutation` instance. This is the underlying state that observer results (e.g. `MutationObserverResult`) are derived from. diff --git a/docs/framework/angular/reference/interfaces/MutationObserverIdleResult.md b/docs/framework/angular/reference/interfaces/MutationObserverIdleResult.md index 99f588acdc4..95af05c592b 100644 --- a/docs/framework/angular/reference/interfaces/MutationObserverIdleResult.md +++ b/docs/framework/angular/reference/interfaces/MutationObserverIdleResult.md @@ -3,7 +3,7 @@ id: MutationObserverIdleResult title: MutationObserverIdleResult --- -Defined in: [packages/query-core/src/types.ts:1520](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1520) +Defined in: packages/query-core/dist-ts/src/types.d.ts:871 The raw state stored on a `Mutation` instance. This is the underlying state that observer results (e.g. `MutationObserverResult`) are derived from. diff --git a/docs/framework/angular/reference/interfaces/MutationObserverLoadingResult.md b/docs/framework/angular/reference/interfaces/MutationObserverLoadingResult.md index 8c39fb8ae1b..d8c98115f91 100644 --- a/docs/framework/angular/reference/interfaces/MutationObserverLoadingResult.md +++ b/docs/framework/angular/reference/interfaces/MutationObserverLoadingResult.md @@ -3,7 +3,7 @@ id: MutationObserverLoadingResult title: MutationObserverLoadingResult --- -Defined in: [packages/query-core/src/types.ts:1541](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1541) +Defined in: packages/query-core/dist-ts/src/types.d.ts:881 The raw state stored on a `Mutation` instance. This is the underlying state that observer results (e.g. `MutationObserverResult`) are derived from. diff --git a/docs/framework/angular/reference/interfaces/MutationObserverOptions.md b/docs/framework/angular/reference/interfaces/MutationObserverOptions.md index 042160d3040..61bc23d2bcf 100644 --- a/docs/framework/angular/reference/interfaces/MutationObserverOptions.md +++ b/docs/framework/angular/reference/interfaces/MutationObserverOptions.md @@ -3,7 +3,7 @@ id: MutationObserverOptions title: MutationObserverOptions --- -Defined in: [packages/query-core/src/types.ts:1387](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1387) +Defined in: packages/query-core/dist-ts/src/types.d.ts:788 ## Extends @@ -29,18 +29,18 @@ Defined in: [packages/query-core/src/types.ts:1387](https://github.com/TanStack/ ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `gcTime?` | `number` | `undefined` | The time in milliseconds that an unused/inactive mutation remains in memory before it is garbage collected. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. | -| `meta?` | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on the mutation cache entry. Use it to pass information that can be read wherever the `mutation` is available, such as the `onError` and `onSuccess` callbacks of the `MutationCache`. | -| `mutationFn?` | (`variables`: `TVariables`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `Promise`\<`TData`\> | `undefined` | The function that performs the asynchronous task this mutation runs. Required, unless a default mutation function has been set for the matching `mutationKey` via `queryClient.setMutationDefaults`. Receives the `variables` passed to `mutate`, and a [MutationFunctionContext](../type-aliases/MutationFunctionContext.md) holding the `QueryClient`, the `mutationKey` and `meta`. Must return a promise that resolves the mutation's data. | -| `mutationKey?` | readonly `unknown`[] | `undefined` | The key to use for this mutation. Optional, but required to inherit defaults registered with `queryClient.setMutationDefaults`, and to match this mutation with `useMutationState` or `queryClient.isMutating`. | -| `networkMode?` | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a mutation is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| `onError?` | (`error`: `TError`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | `undefined` | This function fires when the mutation encounters an error, and is passed the error. If a promise is returned, it is awaited before `onSettled` runs. | -| `onMutate?` | (`variables`: `TVariables`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `TOnMutateResult` \| `Promise`\<`TOnMutateResult`\> | `undefined` | This function fires before the mutation function runs, and receives the same variables. Useful for optimistic updates applied in the hope that the mutation succeeds. The value it returns is passed to `onSuccess`, `onError` and `onSettled` as `onMutateResult`, which is where an optimistic update is usually rolled back. If a promise is returned, it is awaited before the mutation function runs. | -| `onSettled?` | (`data`: `TData` \| `undefined`, `error`: `TError` \| `null`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | `undefined` | This function fires when the mutation either succeeds or errors, and is passed either the data or the error. If a promise is returned, it is awaited before the mutation settles. | -| `onSuccess?` | (`data`: `TData`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | `undefined` | This function fires when the mutation succeeds, and is passed the mutation's result. If a promise is returned, it is awaited before `onSettled` runs. | -| `retry?` | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `0` | If `false`, failed mutations will not retry by default. If `true`, failed mutations will retry infinitely. If set to an integer number, e.g. 3, failed mutations will retry until the failed mutation count meets that number. If set to a function `(failureCount, error) => boolean` failed mutations will retry until the function returns false. | -| `retryDelay?` | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| `scope?` | [`MutationScope`](../type-aliases/MutationScope.md) | `undefined` | Controls whether this mutation runs alongside others or waits its turn. Mutations sharing the same `scope.id` run serially, in the order they were started. Without a scope, a mutation runs as soon as it is triggered. | -| `throwOnError?` | `boolean` \| (`error`: `TError`) => `boolean` | `false` | Whether errors should be thrown instead of setting the `error` property. If set to `true`, all errors will be thrown to the nearest error boundary. If set to a function, it will be passed the error and should return a boolean indicating whether to throw the error (`true`) or return it as state (`false`). | +| Property | Type | Description | +| ------ | ------ | ------ | +| `gcTime?` | `number` | The time in milliseconds that an unused/inactive mutation remains in memory before it is garbage collected. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. | +| `meta?` | `Record`\<`string`, `unknown`\> | - | +| `mutationFn?` | [`MutationFunction`](../type-aliases/MutationFunction.md)\<`TData`, `TVariables`\> | - | +| `mutationKey?` | readonly `unknown`[] | - | +| `networkMode?` | [`NetworkMode`](../type-aliases/NetworkMode.md) | Controls whether a mutation is allowed to run based on the current network connectivity. Defaults to `'online'`. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| `onError?` | (`error`: `TError`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | - | +| `onMutate?` | (`variables`: `TVariables`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `TOnMutateResult` \| `Promise`\<`TOnMutateResult`\> | - | +| `onSettled?` | (`data`: `TData` \| `undefined`, `error`: `TError` \| `null`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | - | +| `onSuccess?` | (`data`: `TData`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | - | +| `retry?` | `RetryValue`\<`TError`\> | If `false`, failed mutations will not retry by default. If `true`, failed mutations will retry infinitely. If set to an integer number, e.g. 3, failed mutations will retry until the failed mutation count meets that number. If set to a function `(failureCount, error) => boolean` failed mutations will retry until the function returns false. Defaults to `0`. | +| `retryDelay?` | `RetryDelayValue`\<`TError`\> | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. Defaults to a function that applies exponential backoff, capped at 30 seconds. | +| `scope?` | [`MutationScope`](../type-aliases/MutationScope.md) | - | +| `throwOnError?` | `boolean` \| (`error`: `TError`) => `boolean` | Whether errors should be thrown instead of setting the `error` property. If set to `true`, all errors will be thrown to the nearest error boundary. If set to a function, it will be passed the error and should return a boolean indicating whether to throw the error (`true`) or return it as state (`false`). Defaults to `false`. | diff --git a/docs/framework/angular/reference/interfaces/MutationObserverSuccessResult.md b/docs/framework/angular/reference/interfaces/MutationObserverSuccessResult.md index 91fe2db58b6..30b976643cf 100644 --- a/docs/framework/angular/reference/interfaces/MutationObserverSuccessResult.md +++ b/docs/framework/angular/reference/interfaces/MutationObserverSuccessResult.md @@ -3,7 +3,7 @@ id: MutationObserverSuccessResult title: MutationObserverSuccessResult --- -Defined in: [packages/query-core/src/types.ts:1583](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1583) +Defined in: packages/query-core/dist-ts/src/types.d.ts:901 The raw state stored on a `Mutation` instance. This is the underlying state that observer results (e.g. `MutationObserverResult`) are derived from. diff --git a/docs/framework/angular/reference/interfaces/MutationOptions.md b/docs/framework/angular/reference/interfaces/MutationOptions.md index b002d91400f..f475ace8e8b 100644 --- a/docs/framework/angular/reference/interfaces/MutationOptions.md +++ b/docs/framework/angular/reference/interfaces/MutationOptions.md @@ -3,7 +3,7 @@ id: MutationOptions title: MutationOptions --- -Defined in: [packages/query-core/src/types.ts:1277](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1277) +Defined in: packages/query-core/dist-ts/src/types.d.ts:746 ## Extended by @@ -29,17 +29,17 @@ Defined in: [packages/query-core/src/types.ts:1277](https://github.com/TanStack/ ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `gcTime?` | `number` | `undefined` | The time in milliseconds that an unused/inactive mutation remains in memory before it is garbage collected. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. | -| `meta?` | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on the mutation cache entry. Use it to pass information that can be read wherever the `mutation` is available, such as the `onError` and `onSuccess` callbacks of the `MutationCache`. | -| `mutationFn?` | (`variables`: `TVariables`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `Promise`\<`TData`\> | `undefined` | The function that performs the asynchronous task this mutation runs. Required, unless a default mutation function has been set for the matching `mutationKey` via `queryClient.setMutationDefaults`. Receives the `variables` passed to `mutate`, and a [MutationFunctionContext](../type-aliases/MutationFunctionContext.md) holding the `QueryClient`, the `mutationKey` and `meta`. Must return a promise that resolves the mutation's data. | -| `mutationKey?` | readonly `unknown`[] | `undefined` | The key to use for this mutation. Optional, but required to inherit defaults registered with `queryClient.setMutationDefaults`, and to match this mutation with `useMutationState` or `queryClient.isMutating`. | -| `networkMode?` | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a mutation is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| `onError?` | (`error`: `TError`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | `undefined` | This function fires when the mutation encounters an error, and is passed the error. If a promise is returned, it is awaited before `onSettled` runs. | -| `onMutate?` | (`variables`: `TVariables`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `TOnMutateResult` \| `Promise`\<`TOnMutateResult`\> | `undefined` | This function fires before the mutation function runs, and receives the same variables. Useful for optimistic updates applied in the hope that the mutation succeeds. The value it returns is passed to `onSuccess`, `onError` and `onSettled` as `onMutateResult`, which is where an optimistic update is usually rolled back. If a promise is returned, it is awaited before the mutation function runs. | -| `onSettled?` | (`data`: `TData` \| `undefined`, `error`: `TError` \| `null`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | `undefined` | This function fires when the mutation either succeeds or errors, and is passed either the data or the error. If a promise is returned, it is awaited before the mutation settles. | -| `onSuccess?` | (`data`: `TData`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | `undefined` | This function fires when the mutation succeeds, and is passed the mutation's result. If a promise is returned, it is awaited before `onSettled` runs. | -| `retry?` | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `0` | If `false`, failed mutations will not retry by default. If `true`, failed mutations will retry infinitely. If set to an integer number, e.g. 3, failed mutations will retry until the failed mutation count meets that number. If set to a function `(failureCount, error) => boolean` failed mutations will retry until the function returns false. | -| `retryDelay?` | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| `scope?` | [`MutationScope`](../type-aliases/MutationScope.md) | `undefined` | Controls whether this mutation runs alongside others or waits its turn. Mutations sharing the same `scope.id` run serially, in the order they were started. Without a scope, a mutation runs as soon as it is triggered. | +| Property | Type | Description | +| ------ | ------ | ------ | +| `gcTime?` | `number` | The time in milliseconds that an unused/inactive mutation remains in memory before it is garbage collected. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. | +| `meta?` | `Record`\<`string`, `unknown`\> | - | +| `mutationFn?` | [`MutationFunction`](../type-aliases/MutationFunction.md)\<`TData`, `TVariables`\> | - | +| `mutationKey?` | readonly `unknown`[] | - | +| `networkMode?` | [`NetworkMode`](../type-aliases/NetworkMode.md) | Controls whether a mutation is allowed to run based on the current network connectivity. Defaults to `'online'`. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| `onError?` | (`error`: `TError`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | - | +| `onMutate?` | (`variables`: `TVariables`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `TOnMutateResult` \| `Promise`\<`TOnMutateResult`\> | - | +| `onSettled?` | (`data`: `TData` \| `undefined`, `error`: `TError` \| `null`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult` \| `undefined`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | - | +| `onSuccess?` | (`data`: `TData`, `variables`: `TVariables`, `onMutateResult`: `TOnMutateResult`, `context`: [`MutationFunctionContext`](../type-aliases/MutationFunctionContext.md)) => `unknown` | - | +| `retry?` | `RetryValue`\<`TError`\> | If `false`, failed mutations will not retry by default. If `true`, failed mutations will retry infinitely. If set to an integer number, e.g. 3, failed mutations will retry until the failed mutation count meets that number. If set to a function `(failureCount, error) => boolean` failed mutations will retry until the function returns false. Defaults to `0`. | +| `retryDelay?` | `RetryDelayValue`\<`TError`\> | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. Defaults to a function that applies exponential backoff, capped at 30 seconds. | +| `scope?` | [`MutationScope`](../type-aliases/MutationScope.md) | - | diff --git a/docs/framework/angular/reference/interfaces/MutationState.md b/docs/framework/angular/reference/interfaces/MutationState.md index 62ce6ac5cde..25f25dfa37f 100644 --- a/docs/framework/angular/reference/interfaces/MutationState.md +++ b/docs/framework/angular/reference/interfaces/MutationState.md @@ -3,7 +3,7 @@ id: MutationState title: MutationState --- -Defined in: [packages/query-core/src/mutation.ts:30](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutation.ts#L30) +Defined in: packages/query-core/dist-ts/src/mutation.d.ts:17 The raw state stored on a `Mutation` instance. This is the underlying state that observer results (e.g. `MutationObserverResult`) are derived from. @@ -40,6 +40,6 @@ that observer results (e.g. `MutationObserverResult`) are derived from. | `failureCount` | `number` | The number of times the mutation function has failed for the current attempt. | | `failureReason` | `TError` \| `null` | The reason the current attempt failed, as reported by the retryer. | | `isPaused` | `boolean` | Whether the mutation is currently paused (see network mode), or is waiting for another mutation with the same `scope` to finish. | -| `status` | `"error"` \| `"pending"` \| `"success"` \| `"idle"` | The status of the mutation. | +| `status` | [`MutationStatus`](../type-aliases/MutationStatus.md) | The status of the mutation. | | `submittedAt` | `number` | The timestamp for when the mutation was submitted. | | `variables` | `TVariables` \| `undefined` | The variables the mutation was last called with. | diff --git a/docs/framework/angular/reference/interfaces/NotifyEvent.md b/docs/framework/angular/reference/interfaces/NotifyEvent.md index b4af1d74174..76c51ab1221 100644 --- a/docs/framework/angular/reference/interfaces/NotifyEvent.md +++ b/docs/framework/angular/reference/interfaces/NotifyEvent.md @@ -3,10 +3,10 @@ id: NotifyEvent title: NotifyEvent --- -Defined in: [packages/query-core/src/types.ts:1669](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1669) +Defined in: packages/query-core/dist-ts/src/types.d.ts:941 ## Properties | Property | Type | | ------ | ------ | -| `type` | \| `"added"` \| `"removed"` \| `"updated"` \| `"observerAdded"` \| `"observerRemoved"` \| `"observerResultsUpdated"` \| `"observerOptionsUpdated"` | +| `type` | [`NotifyEventType`](../type-aliases/NotifyEventType.md) | diff --git a/docs/framework/angular/reference/interfaces/OnlineManager.md b/docs/framework/angular/reference/interfaces/OnlineManager.md index e9f911fce4e..eb7d8910d74 100644 --- a/docs/framework/angular/reference/interfaces/OnlineManager.md +++ b/docs/framework/angular/reference/interfaces/OnlineManager.md @@ -3,7 +3,7 @@ id: OnlineManager title: OnlineManager --- -Defined in: [packages/query-core/src/onlineManager.ts:15](https://github.com/TanStack/query/blob/main/packages/query-core/src/onlineManager.ts#L15) +Defined in: packages/query-core/dist-ts/src/onlineManager.d.ts:13 The `OnlineManager` manages the online state within TanStack Query. It can be used to change the default event listeners or to manually change the @@ -31,9 +31,7 @@ detect changes. hasListeners(): boolean; ``` -Defined in: [packages/query-core/src/subscribable.ts:41](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L41) - -Returns `true` while at least one listener is registered, `false` once they have all unsubscribed. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:5 #### Returns @@ -53,7 +51,7 @@ Subscribable.hasListeners isOnline(): boolean; ``` -Defined in: [packages/query-core/src/onlineManager.ts:109](https://github.com/TanStack/query/blob/main/packages/query-core/src/onlineManager.ts#L109) +Defined in: packages/query-core/dist-ts/src/onlineManager.d.ts:55 `isOnline` can be used to get the current online state. @@ -69,7 +67,7 @@ Defined in: [packages/query-core/src/onlineManager.ts:109](https://github.com/Ta protected onSubscribe(): void; ``` -Defined in: [packages/query-core/src/onlineManager.ts:44](https://github.com/TanStack/query/blob/main/packages/query-core/src/onlineManager.ts#L44) +Defined in: packages/query-core/dist-ts/src/onlineManager.d.ts:16 #### Returns @@ -89,7 +87,7 @@ Subscribable.onSubscribe protected onUnsubscribe(): void; ``` -Defined in: [packages/query-core/src/onlineManager.ts:50](https://github.com/TanStack/query/blob/main/packages/query-core/src/onlineManager.ts#L50) +Defined in: packages/query-core/dist-ts/src/onlineManager.d.ts:17 #### Returns @@ -109,7 +107,7 @@ Subscribable.onUnsubscribe setEventListener(setup: SetupFn): void; ``` -Defined in: [packages/query-core/src/onlineManager.ts:75](https://github.com/TanStack/query/blob/main/packages/query-core/src/onlineManager.ts#L75) +Defined in: packages/query-core/dist-ts/src/onlineManager.d.ts:36 `setEventListener` can be used to set a custom event listener that will be used to determine the online state. The provided `setup` function @@ -147,7 +145,7 @@ onlineManager.setEventListener((setOnline) => { setOnline(online: boolean): void; ``` -Defined in: [packages/query-core/src/onlineManager.ts:95](https://github.com/TanStack/query/blob/main/packages/query-core/src/onlineManager.ts#L95) +Defined in: packages/query-core/dist-ts/src/onlineManager.d.ts:51 `setOnline` can be used to manually set the online state. @@ -181,11 +179,7 @@ onlineManager.setOnline(false) subscribe(listener: Listener): () => void; ``` -Defined in: [packages/query-core/src/subscribable.ts:27](https://github.com/TanStack/query/blob/main/packages/query-core/src/subscribable.ts#L27) - -Registers a listener to be called on every update this object notifies about. Returns a function -that removes the listener again — call it to stop listening. The base class never drops a listener -on its own, though some subclasses clear all of theirs in `destroy()`. +Defined in: packages/query-core/dist-ts/src/subscribable.d.ts:4 #### Parameters diff --git a/docs/framework/angular/reference/interfaces/QueriesObserverOptions.md b/docs/framework/angular/reference/interfaces/QueriesObserverOptions.md index 012d9eb948b..70bb3a45d80 100644 --- a/docs/framework/angular/reference/interfaces/QueriesObserverOptions.md +++ b/docs/framework/angular/reference/interfaces/QueriesObserverOptions.md @@ -3,7 +3,7 @@ id: QueriesObserverOptions title: QueriesObserverOptions --- -Defined in: [packages/query-core/src/queriesObserver.ts:23](https://github.com/TanStack/query/blob/main/packages/query-core/src/queriesObserver.ts#L23) +Defined in: packages/query-core/dist-ts/src/queriesObserver.d.ts:7 ## Type Parameters diff --git a/docs/framework/angular/reference/interfaces/QueryCacheConfig.md b/docs/framework/angular/reference/interfaces/QueryCacheConfig.md index b0742235c17..a0b93d89af1 100644 --- a/docs/framework/angular/reference/interfaces/QueryCacheConfig.md +++ b/docs/framework/angular/reference/interfaces/QueryCacheConfig.md @@ -3,7 +3,7 @@ id: QueryCacheConfig title: QueryCacheConfig --- -Defined in: [packages/query-core/src/queryCache.ts:25](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryCache.ts#L25) +Defined in: packages/query-core/dist-ts/src/queryCache.d.ts:14 Global callbacks that fire for every query handled by a `QueryCache`, regardless of which component or observer triggered it. Unlike `QueryClient`'s `defaultOptions`, which a query can diff --git a/docs/framework/angular/reference/interfaces/QueryClientConfig.md b/docs/framework/angular/reference/interfaces/QueryClientConfig.md index 4608d496bb6..f635ca6dfb9 100644 --- a/docs/framework/angular/reference/interfaces/QueryClientConfig.md +++ b/docs/framework/angular/reference/interfaces/QueryClientConfig.md @@ -3,7 +3,7 @@ id: QueryClientConfig title: QueryClientConfig --- -Defined in: [packages/query-core/src/types.ts:1615](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1615) +Defined in: packages/query-core/dist-ts/src/types.d.ts:912 ## Properties diff --git a/docs/framework/angular/reference/interfaces/QueryExecuteOptions.md b/docs/framework/angular/reference/interfaces/QueryExecuteOptions.md index 70770fe13b6..854451559c5 100644 --- a/docs/framework/angular/reference/interfaces/QueryExecuteOptions.md +++ b/docs/framework/angular/reference/interfaces/QueryExecuteOptions.md @@ -3,7 +3,7 @@ id: QueryExecuteOptions title: QueryExecuteOptions --- -Defined in: [packages/query-core/src/types.ts:629](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L629) +Defined in: packages/query-core/dist-ts/src/types.d.ts:322 ## Extends @@ -37,22 +37,22 @@ Defined in: [packages/query-core/src/types.ts:629](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `gcTime?` | `number` | `undefined` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | -| `initialData?` | `TQueryData` \| () => `TQueryData` \| `undefined` | `undefined` | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | -| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | -| `initialPageParam?` | `undefined` | `undefined` | - | -| `maxPages?` | `number` | `undefined` | Maximum number of pages to store in the data of an infinite query. | -| `meta?` | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | -| `networkMode?` | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a query is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| `persister?` | (`queryFn`: (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`NoInfer`\<`TQueryKey`\>, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\>, `context`: `object`, `query`: [`Query`](../classes/Query.md)) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | -| `queryFn?` | \| *typeof* [`skipToken`](../variables/skipToken.md) \| (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`TQueryKey`, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | -| `queryHash?` | `string` | `undefined` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | -| `queryKey` | `TQueryKey` & `object` | `undefined` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | -| `queryKeyHashFn?` | (`queryKey`: `TQueryKey`) => `string` | `undefined` | If specified, this function is used to hash the `queryKey` to a string. | -| `retry?` | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `undefined` | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | -| `retryDelay?` | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| `select?` | (`data`: `TQueryData`) => `TData` | `undefined` | This option can be used to transform or select a part of the data returned by the query function. It affects the value this call resolves with, but does not affect what gets stored in the query cache. | -| `staleTime?` | \| `number` \| `"static"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `number` \| `"static"` | `undefined` | The time in milliseconds after data is considered stale. If the data is fresh it will be returned from the cache. | -| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | `true` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. | +| Property | Type | Description | +| ------ | ------ | ------ | +| `gcTime?` | `number` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | +| `initialData?` | \| `TQueryData` \| [`InitialDataFunction`](../type-aliases/InitialDataFunction.md)\<`TQueryData`\> | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | +| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | +| `initialPageParam?` | `undefined` | - | +| `maxPages?` | `number` | Maximum number of pages to store in the data of an infinite query. | +| `meta?` | `Record`\<`string`, `unknown`\> | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | +| `networkMode?` | [`NetworkMode`](../type-aliases/NetworkMode.md) | Controls whether a query is allowed to run based on the current network connectivity. Defaults to `'online'`. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| `persister?` | [`QueryPersister`](../type-aliases/QueryPersister.md)\<`TQueryFnData`, `NoInfer`\<`TQueryKey`\>, `TPageParam`\> | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | +| `queryFn?` | \| *typeof* [`skipToken`](../variables/skipToken.md) \| [`QueryFunction`](../type-aliases/QueryFunction.md)\<`TQueryFnData`, `TQueryKey`, `TPageParam`\> | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | +| `queryHash?` | `string` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | +| `queryKey` | `TQueryKey` & `object` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | +| `queryKeyHashFn?` | [`QueryKeyHashFunction`](../type-aliases/QueryKeyHashFunction.md)\<`TQueryKey`\> | If specified, this function is used to hash the `queryKey` to a string. | +| `retry?` | `RetryValue`\<`TError`\> | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | +| `retryDelay?` | `RetryDelayValue`\<`TError`\> | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | +| `select?` | (`data`: `TQueryData`) => `TData` | - | +| `staleTime?` | [`StaleTimeFunction`](../type-aliases/StaleTimeFunction.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\> | The time in milliseconds after data is considered stale. If the data is fresh it will be returned from the cache. | +| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. Defaults to `true`. | diff --git a/docs/framework/angular/reference/interfaces/QueryFeature.md b/docs/framework/angular/reference/interfaces/QueryFeature.md index c65d634a369..8937378ea98 100644 --- a/docs/framework/angular/reference/interfaces/QueryFeature.md +++ b/docs/framework/angular/reference/interfaces/QueryFeature.md @@ -3,15 +3,7 @@ id: QueryFeature title: QueryFeature --- -An opaque configuration returned by Query feature functions. Pass these values to -`provideTanStackQuery`; application code does not construct or inspect them. +Defined in: [packages/angular-query/src/providers.ts:122](https://github.com/TanStack/query/blob/main/packages/angular-query/src/providers.ts#L122) -```ts -provideTanStackQuery( - () => new QueryClient(), - withHydrationKey('secondary-cache'), -) -``` - -See [provideTanStackQuery](../functions/provideTanStackQuery.md) for provider setup -and [SSR](../../guides/ssr.md) for hydration features. +Opaque configuration returned by Query feature functions such as `withHydrationKey`. +Pass features to `provideTanStackQuery`; applications do not construct them directly. diff --git a/docs/framework/angular/reference/interfaces/QueryFilters.md b/docs/framework/angular/reference/interfaces/QueryFilters.md index 7d866400365..e0f151eba8f 100644 --- a/docs/framework/angular/reference/interfaces/QueryFilters.md +++ b/docs/framework/angular/reference/interfaces/QueryFilters.md @@ -3,7 +3,7 @@ id: QueryFilters title: QueryFilters --- -Defined in: [packages/query-core/src/utils.ts:31](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L31) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:13 Filters used to select queries, for example in `queryClient.getQueriesData` or `queryClient.invalidateQueries`. All provided filters must match; filters that are left unspecified are ignored. @@ -21,11 +21,11 @@ All provided filters must match; filters that are left unspecified are ignored. ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `exact?` | `boolean` | `undefined` | Match query key exactly | -| `fetchStatus?` | `"fetching"` \| `"paused"` \| `"idle"` | `undefined` | Include queries matching their fetchStatus | -| `predicate?` | (`query`: [`Query`](../classes/Query.md)) => `boolean` | `undefined` | Include queries matching this predicate function | -| `queryKey?` | `TQueryKey` \| `TuplePrefixes`\<`TQueryKey`\> | `undefined` | Include queries matching this query key | -| `stale?` | `boolean` | `undefined` | Include or exclude stale queries | -| `type?` | `QueryTypeFilter` | `'all'` | Filter to active queries, inactive queries or all queries | +| Property | Type | Description | +| ------ | ------ | ------ | +| `exact?` | `boolean` | Match query key exactly | +| `fetchStatus?` | [`FetchStatus`](../type-aliases/FetchStatus.md) | Include queries matching their fetchStatus | +| `predicate?` | (`query`: [`Query`](../classes/Query.md)) => `boolean` | Include queries matching this predicate function | +| `queryKey?` | `TQueryKey` \| `TuplePrefixes`\<`TQueryKey`\> | Include queries matching this query key | +| `stale?` | `boolean` | Include or exclude stale queries | +| `type?` | `QueryTypeFilter` | Filter to active queries, inactive queries or all queries Defaults to `'all'`. | diff --git a/docs/framework/angular/reference/interfaces/QueryObserverBaseResult.md b/docs/framework/angular/reference/interfaces/QueryObserverBaseResult.md index 754fae8f604..5256d31a4b2 100644 --- a/docs/framework/angular/reference/interfaces/QueryObserverBaseResult.md +++ b/docs/framework/angular/reference/interfaces/QueryObserverBaseResult.md @@ -3,7 +3,7 @@ id: QueryObserverBaseResult title: QueryObserverBaseResult --- -Defined in: [packages/query-core/src/types.ts:826](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L826) +Defined in: packages/query-core/dist-ts/src/types.d.ts:418 ## Extended by @@ -36,7 +36,7 @@ Defined in: [packages/query-core/src/types.ts:826](https://github.com/TanStack/q | `errorUpdatedAt` | `number` | The timestamp for when the query most recently returned the `status` as `"error"`. | | `failureCount` | `number` | The failure count for the query. - Incremented every time the query fails. - Reset to `0` when the query succeeds. | | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | | `isError` | `boolean` | A derived boolean from the `status` variable, provided for convenience. - `true` if the query attempt resulted in an error. | | `isFetched` | `boolean` | Will be `true` if the query has been fetched. | @@ -53,4 +53,4 @@ Defined in: [packages/query-core/src/types.ts:826](https://github.com/TanStack/q | `isStale` | `boolean` | Will be `true` if the data in the cache is invalidated or if the data is older than the given `staleTime`. | | `isSuccess` | `boolean` | A derived boolean from the `status` variable, provided for convenience. - `true` if the query has received a response with no errors and is ready to display its data. | | `refetch` | (`options?`: [`RefetchOptions`](RefetchOptions.md)) => `Promise`\<[`QueryObserverResult`](../type-aliases/QueryObserverResult.md)\<`TData`, `TError`\>\> | A function to manually refetch the query. | -| `status` | `"error"` \| `"pending"` \| `"success"` | The status of the query. - Will be: - `pending` if there's no cached data and no query attempt was finished yet. - `error` if the query attempt resulted in an error. - `success` if the query has received a response with no errors and is ready to display its data. | +| `status` | [`QueryStatus`](../type-aliases/QueryStatus.md) | The status of the query. - Will be: - `pending` if there's no cached data and no query attempt was finished yet. - `error` if the query attempt resulted in an error. - `success` if the query has received a response with no errors and is ready to display its data. | diff --git a/docs/framework/angular/reference/interfaces/QueryObserverLoadingErrorResult.md b/docs/framework/angular/reference/interfaces/QueryObserverLoadingErrorResult.md index c8a355c7382..bee8e1fdbc0 100644 --- a/docs/framework/angular/reference/interfaces/QueryObserverLoadingErrorResult.md +++ b/docs/framework/angular/reference/interfaces/QueryObserverLoadingErrorResult.md @@ -3,7 +3,7 @@ id: QueryObserverLoadingErrorResult title: QueryObserverLoadingErrorResult --- -Defined in: [packages/query-core/src/types.ts:985](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L985) +Defined in: packages/query-core/dist-ts/src/types.d.ts:563 ## Extends @@ -30,7 +30,7 @@ Defined in: [packages/query-core/src/types.ts:985](https://github.com/TanStack/q | `errorUpdatedAt` | `number` | The timestamp for when the query most recently returned the `status` as `"error"`. | - | | `failureCount` | `number` | The failure count for the query. - Incremented every time the query fails. - Reset to `0` when the query succeeds. | - | | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | | `isError` | `true` | A derived boolean from the `status` variable, provided for convenience. - `true` if the query attempt resulted in an error. | [`QueryObserverBaseResult`](QueryObserverBaseResult.md).[`isError`](QueryObserverBaseResult.md#iserror) | | `isFetched` | `boolean` | Will be `true` if the query has been fetched. | - | diff --git a/docs/framework/angular/reference/interfaces/QueryObserverLoadingResult.md b/docs/framework/angular/reference/interfaces/QueryObserverLoadingResult.md index 01cda76e32c..34fe7f9662d 100644 --- a/docs/framework/angular/reference/interfaces/QueryObserverLoadingResult.md +++ b/docs/framework/angular/reference/interfaces/QueryObserverLoadingResult.md @@ -3,7 +3,7 @@ id: QueryObserverLoadingResult title: QueryObserverLoadingResult --- -Defined in: [packages/query-core/src/types.ts:969](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L969) +Defined in: packages/query-core/dist-ts/src/types.d.ts:551 ## Extends @@ -30,7 +30,7 @@ Defined in: [packages/query-core/src/types.ts:969](https://github.com/TanStack/q | `errorUpdatedAt` | `number` | The timestamp for when the query most recently returned the `status` as `"error"`. | - | | `failureCount` | `number` | The failure count for the query. - Incremented every time the query fails. - Reset to `0` when the query succeeds. | - | | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | | `isError` | `false` | A derived boolean from the `status` variable, provided for convenience. - `true` if the query attempt resulted in an error. | [`QueryObserverBaseResult`](QueryObserverBaseResult.md).[`isError`](QueryObserverBaseResult.md#iserror) | | `isFetched` | `boolean` | Will be `true` if the query has been fetched. | - | diff --git a/docs/framework/angular/reference/interfaces/QueryObserverOptions.md b/docs/framework/angular/reference/interfaces/QueryObserverOptions.md index 8722cbd51af..ff5eb99607e 100644 --- a/docs/framework/angular/reference/interfaces/QueryObserverOptions.md +++ b/docs/framework/angular/reference/interfaces/QueryObserverOptions.md @@ -3,7 +3,7 @@ id: QueryObserverOptions title: QueryObserverOptions --- -Defined in: [packages/query-core/src/types.ts:435](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L435) +Defined in: packages/query-core/dist-ts/src/types.d.ts:210 ## Extends @@ -41,32 +41,32 @@ Defined in: [packages/query-core/src/types.ts:435](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `enabled?` | \| `false` \| `true` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` | `true` | Set this to `false` or a function that returns `false` to disable automatic refetching when the query mounts or changes query keys. To refetch the query, use the `refetch` method returned from the `useQuery` instance. Accepts a boolean or function that returns a boolean. | -| `gcTime?` | `number` | `undefined` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | -| `initialData?` | `TQueryData` \| () => `TQueryData` \| `undefined` | `undefined` | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | -| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | -| `maxPages?` | `number` | `undefined` | Maximum number of pages to store in the data of an infinite query. | -| `meta?` | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | -| `networkMode?` | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a query is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| `notifyOnChangeProps?` | \| ( \| `"error"` \| `"data"` \| `"isError"` \| `"isPending"` \| `"isLoading"` \| `"isLoadingError"` \| `"isRefetchError"` \| `"isSuccess"` \| `"isPlaceholderData"` \| `"status"` \| `"dataUpdatedAt"` \| `"errorUpdatedAt"` \| `"failureCount"` \| `"failureReason"` \| `"errorUpdateCount"` \| `"isFetched"` \| `"isFetchedAfterMount"` \| `"isFetching"` \| `"isInitialLoading"` \| `"isPaused"` \| `"isRefetching"` \| `"isStale"` \| `"isEnabled"` \| `"refetch"` \| `"fetchStatus"` \| `"fetchNextPage"` \| `"fetchPreviousPage"` \| `"hasNextPage"` \| `"hasPreviousPage"` \| `"isFetchNextPageError"` \| `"isFetchingNextPage"` \| `"isFetchPreviousPageError"` \| `"isFetchingPreviousPage"`)[] \| `"all"` \| () => \| `"all"` \| ( \| `"error"` \| `"data"` \| `"isError"` \| `"isPending"` \| `"isLoading"` \| `"isLoadingError"` \| `"isRefetchError"` \| `"isSuccess"` \| `"isPlaceholderData"` \| `"status"` \| `"dataUpdatedAt"` \| `"errorUpdatedAt"` \| `"failureCount"` \| `"failureReason"` \| `"errorUpdateCount"` \| `"isFetched"` \| `"isFetchedAfterMount"` \| `"isFetching"` \| `"isInitialLoading"` \| `"isPaused"` \| `"isRefetching"` \| `"isStale"` \| `"isEnabled"` \| `"refetch"` \| `"fetchStatus"` \| `"fetchNextPage"` \| `"fetchPreviousPage"` \| `"hasNextPage"` \| `"hasPreviousPage"` \| `"isFetchNextPageError"` \| `"isFetchingNextPage"` \| `"isFetchPreviousPageError"` \| `"isFetchingPreviousPage"`)[] \| `undefined` | `undefined` | If set, the component will only re-render if any of the listed properties change. When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change. When set to `'all'`, the component will re-render whenever a query is updated. When set to a function, the function will be executed to compute the list of properties. Defaults to `undefined`, in which case property access is tracked automatically, and the component only re-renders when one of the tracked properties changes. | -| `persister?` | (`queryFn`: (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`NoInfer`\<`TQueryKey`\>, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\>, `context`: `object`, `query`: [`Query`](../classes/Query.md)) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | -| `placeholderData?` | \| `NonFunctionGuard`\<`TQueryData`\> \| (`previousData`: `NonFunctionGuard`\<`TQueryData`\> \| `undefined`, `previousQuery`: \| [`Query`](../classes/Query.md)\<`NonFunctionGuard`\<`TQueryData`\>, `TError`, `NonFunctionGuard`\<`TQueryData`\>, `TQueryKey`\> \| `undefined`) => `NonFunctionGuard`\<`TQueryData`\> \| `undefined` | `undefined` | If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `loading` data and no initialData has been provided. | -| `queryFn?` | \| *typeof* [`skipToken`](../variables/skipToken.md) \| (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`TQueryKey`, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | -| `queryHash?` | `string` | `undefined` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | -| `queryKey` | `TQueryKey` & `object` | `undefined` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | -| `queryKeyHashFn?` | (`queryKey`: `TQueryKey`) => `string` | `undefined` | If specified, this function is used to hash the `queryKey` to a string. | -| `refetchInterval?` | \| `number` \| `false` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `number` \| `false` \| `undefined` | `false` | If set to a number, the query will continuously refetch at this frequency in milliseconds. If set to a function, the function will be executed with the latest data and query to compute a frequency | -| `refetchIntervalInBackground?` | `boolean` | `false` | If set to `true`, the query will continue to refetch while their tab/window is in the background. | -| `refetchOnMount?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` \| `"always"` | `true` | If set to `true`, the query will refetch on mount if the data is stale. If set to `false`, will disable additional instances of a query to trigger background refetch. If set to `'always'`, the query will always refetch on mount (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value | -| `refetchOnReconnect?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` \| `"always"` | `undefined` | If set to `true`, the query will refetch on reconnect if the data is stale. If set to `false`, the query will not refetch on reconnect. If set to `'always'`, the query will always refetch on reconnect (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. Defaults to `true` unless `networkMode` is `'always'`. | -| `refetchOnWindowFocus?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` \| `"always"` | `true` | If set to `true`, the query will refetch on window focus if the data is stale. If set to `false`, the query will not refetch on window focus. If set to `'always'`, the query will always refetch on window focus (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. | -| `retry?` | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `undefined` | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | -| `retryDelay?` | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| `retryOnMount?` | \| `false` \| `true` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` | `true` | If set to `false`, the query will not be retried on mount if it contains an error. If set to a function, the function will be executed with the query to compute the value. | -| `select?` | (`data`: `TQueryData`) => `TData` | `undefined` | This option can be used to transform or select a part of the data returned by the query function. It affects the returned `data` value, but does not affect what gets stored in the query cache. The `select` function will only run if `data` changed, or if the reference to the `select` function itself changes. To optimize, memoize the function so its reference stays stable across calls. | -| `staleTime?` | \| `number` \| `"static"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `number` \| `"static"` | `0` | The time in milliseconds after data is considered stale. If set to `Infinity`, the data will never be considered stale. If set to `'static'`, the data will never be considered stale. If set to a function, the function will be executed with the query to compute a `staleTime`. | -| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | `true` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. | -| `suspense?` | `boolean` | `false` | If set to `true`, the query will suspend when `status === 'pending'` and throw errors when `status === 'error'`. | -| `throwOnError?` | \| `false` \| `true` \| (`error`: `TError`, `query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` | `false` | Whether errors should be thrown instead of setting the `error` property. If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary. If set to `false` and `suspense` is `false`, errors are returned as state. If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`). | +| Property | Type | Description | +| ------ | ------ | ------ | +| `enabled?` | [`QueryBooleanOption`](../type-aliases/QueryBooleanOption.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\> | Set this to `false` or a function that returns `false` to disable automatic refetching when the query mounts or changes query keys. To refetch the query, use the `refetch` method returned from the `useQuery` instance. Accepts a boolean or function that returns a boolean. Defaults to `true`. | +| `gcTime?` | `number` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | +| `initialData?` | \| `TQueryData` \| [`InitialDataFunction`](../type-aliases/InitialDataFunction.md)\<`TQueryData`\> | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | +| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | +| `maxPages?` | `number` | Maximum number of pages to store in the data of an infinite query. | +| `meta?` | `Record`\<`string`, `unknown`\> | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | +| `networkMode?` | [`NetworkMode`](../type-aliases/NetworkMode.md) | Controls whether a query is allowed to run based on the current network connectivity. Defaults to `'online'`. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| `notifyOnChangeProps?` | [`NotifyOnChangeProps`](../type-aliases/NotifyOnChangeProps.md) | If set, the component will only re-render if any of the listed properties change. When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change. When set to `'all'`, the component will re-render whenever a query is updated. When set to a function, the function will be executed to compute the list of properties. Defaults to `undefined`, in which case property access is tracked automatically, and the component only re-renders when one of the tracked properties changes. | +| `persister?` | [`QueryPersister`](../type-aliases/QueryPersister.md)\<`TQueryFnData`, `NoInfer`\<`TQueryKey`\>, `TPageParam`\> | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | +| `placeholderData?` | \| `NonFunctionGuard`\<`TQueryData`\> \| [`PlaceholderDataFunction`](../type-aliases/PlaceholderDataFunction.md)\<`NonFunctionGuard`\<`TQueryData`\>, `TError`, `NonFunctionGuard`\<`TQueryData`\>, `TQueryKey`\> | If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `loading` data and no initialData has been provided. | +| `queryFn?` | \| *typeof* [`skipToken`](../variables/skipToken.md) \| [`QueryFunction`](../type-aliases/QueryFunction.md)\<`TQueryFnData`, `TQueryKey`, `TPageParam`\> | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | +| `queryHash?` | `string` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | +| `queryKey` | `TQueryKey` & `object` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | +| `queryKeyHashFn?` | [`QueryKeyHashFunction`](../type-aliases/QueryKeyHashFunction.md)\<`TQueryKey`\> | If specified, this function is used to hash the `queryKey` to a string. | +| `refetchInterval?` | \| `number` \| `false` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `number` \| `false` \| `undefined` | If set to a number, the query will continuously refetch at this frequency in milliseconds. If set to a function, the function will be executed with the latest data and query to compute a frequency Defaults to `false`. | +| `refetchIntervalInBackground?` | `boolean` | If set to `true`, the query will continue to refetch while their tab/window is in the background. Defaults to `false`. | +| `refetchOnMount?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` \| `"always"` | If set to `true`, the query will refetch on mount if the data is stale. If set to `false`, will disable additional instances of a query to trigger background refetch. If set to `'always'`, the query will always refetch on mount (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value Defaults to `true`. | +| `refetchOnReconnect?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` \| `"always"` | If set to `true`, the query will refetch on reconnect if the data is stale. If set to `false`, the query will not refetch on reconnect. If set to `'always'`, the query will always refetch on reconnect (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. Defaults to `true` unless `networkMode` is `'always'`. | +| `refetchOnWindowFocus?` | \| `boolean` \| `"always"` \| (`query`: [`Query`](../classes/Query.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\>) => `boolean` \| `"always"` | If set to `true`, the query will refetch on window focus if the data is stale. If set to `false`, the query will not refetch on window focus. If set to `'always'`, the query will always refetch on window focus (except when `staleTime: 'static'` is used). If set to a function, the function will be executed with the latest data and query to compute the value. Defaults to `true`. | +| `retry?` | `RetryValue`\<`TError`\> | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | +| `retryDelay?` | `RetryDelayValue`\<`TError`\> | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | +| `retryOnMount?` | [`QueryBooleanOption`](../type-aliases/QueryBooleanOption.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\> | If set to `false`, the query will not be retried on mount if it contains an error. If set to a function, the function will be executed with the query to compute the value. Defaults to `true`. | +| `select?` | (`data`: `TQueryData`) => `TData` | This option can be used to transform or select a part of the data returned by the query function. It affects the returned `data` value, but does not affect what gets stored in the query cache. The `select` function will only run if `data` changed, or if the reference to the `select` function itself changes. To optimize, memoize the function so its reference stays stable across calls. | +| `staleTime?` | [`StaleTimeFunction`](../type-aliases/StaleTimeFunction.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\> | The time in milliseconds after data is considered stale. If set to `Infinity`, the data will never be considered stale. If set to `'static'`, the data will never be considered stale. If set to a function, the function will be executed with the query to compute a `staleTime`. Defaults to `0`. | +| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. Defaults to `true`. | +| `suspense?` | `boolean` | If set to `true`, the query will suspend when `status === 'pending'` and throw errors when `status === 'error'`. Defaults to `false`. | +| `throwOnError?` | [`ThrowOnError`](../type-aliases/ThrowOnError.md)\<`TQueryFnData`, `TError`, `TQueryData`, `TQueryKey`\> | Whether errors should be thrown instead of setting the `error` property. If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary. If set to `false` and `suspense` is `false`, errors are returned as state. If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`). Defaults to `false`. | diff --git a/docs/framework/angular/reference/interfaces/QueryObserverPendingResult.md b/docs/framework/angular/reference/interfaces/QueryObserverPendingResult.md index 76ec49eef16..b461c7ce507 100644 --- a/docs/framework/angular/reference/interfaces/QueryObserverPendingResult.md +++ b/docs/framework/angular/reference/interfaces/QueryObserverPendingResult.md @@ -3,7 +3,7 @@ id: QueryObserverPendingResult title: QueryObserverPendingResult --- -Defined in: [packages/query-core/src/types.ts:954](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L954) +Defined in: packages/query-core/dist-ts/src/types.d.ts:540 ## Extends @@ -30,7 +30,7 @@ Defined in: [packages/query-core/src/types.ts:954](https://github.com/TanStack/q | `errorUpdatedAt` | `number` | The timestamp for when the query most recently returned the `status` as `"error"`. | - | | `failureCount` | `number` | The failure count for the query. - Incremented every time the query fails. - Reset to `0` when the query succeeds. | - | | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | | `isError` | `false` | A derived boolean from the `status` variable, provided for convenience. - `true` if the query attempt resulted in an error. | [`QueryObserverBaseResult`](QueryObserverBaseResult.md).[`isError`](QueryObserverBaseResult.md#iserror) | | `isFetched` | `boolean` | Will be `true` if the query has been fetched. | - | diff --git a/docs/framework/angular/reference/interfaces/QueryObserverPlaceholderResult.md b/docs/framework/angular/reference/interfaces/QueryObserverPlaceholderResult.md index 43c5e121c6d..8664a574755 100644 --- a/docs/framework/angular/reference/interfaces/QueryObserverPlaceholderResult.md +++ b/docs/framework/angular/reference/interfaces/QueryObserverPlaceholderResult.md @@ -3,7 +3,7 @@ id: QueryObserverPlaceholderResult title: QueryObserverPlaceholderResult --- -Defined in: [packages/query-core/src/types.ts:1033](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1033) +Defined in: packages/query-core/dist-ts/src/types.d.ts:599 ## Extends @@ -30,7 +30,7 @@ Defined in: [packages/query-core/src/types.ts:1033](https://github.com/TanStack/ | `errorUpdatedAt` | `number` | The timestamp for when the query most recently returned the `status` as `"error"`. | - | | `failureCount` | `number` | The failure count for the query. - Incremented every time the query fails. - Reset to `0` when the query succeeds. | - | | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | | `isError` | `false` | A derived boolean from the `status` variable, provided for convenience. - `true` if the query attempt resulted in an error. | [`QueryObserverBaseResult`](QueryObserverBaseResult.md).[`isError`](QueryObserverBaseResult.md#iserror) | | `isFetched` | `boolean` | Will be `true` if the query has been fetched. | - | diff --git a/docs/framework/angular/reference/interfaces/QueryObserverRefetchErrorResult.md b/docs/framework/angular/reference/interfaces/QueryObserverRefetchErrorResult.md index 6e58e628a33..c6b620348b8 100644 --- a/docs/framework/angular/reference/interfaces/QueryObserverRefetchErrorResult.md +++ b/docs/framework/angular/reference/interfaces/QueryObserverRefetchErrorResult.md @@ -3,7 +3,7 @@ id: QueryObserverRefetchErrorResult title: QueryObserverRefetchErrorResult --- -Defined in: [packages/query-core/src/types.ts:1001](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1001) +Defined in: packages/query-core/dist-ts/src/types.d.ts:575 ## Extends @@ -30,7 +30,7 @@ Defined in: [packages/query-core/src/types.ts:1001](https://github.com/TanStack/ | `errorUpdatedAt` | `number` | The timestamp for when the query most recently returned the `status` as `"error"`. | - | | `failureCount` | `number` | The failure count for the query. - Incremented every time the query fails. - Reset to `0` when the query succeeds. | - | | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | | `isError` | `true` | A derived boolean from the `status` variable, provided for convenience. - `true` if the query attempt resulted in an error. | [`QueryObserverBaseResult`](QueryObserverBaseResult.md).[`isError`](QueryObserverBaseResult.md#iserror) | | `isFetched` | `boolean` | Will be `true` if the query has been fetched. | - | diff --git a/docs/framework/angular/reference/interfaces/QueryObserverSuccessResult.md b/docs/framework/angular/reference/interfaces/QueryObserverSuccessResult.md index ddc15abe6f4..9d023b8f514 100644 --- a/docs/framework/angular/reference/interfaces/QueryObserverSuccessResult.md +++ b/docs/framework/angular/reference/interfaces/QueryObserverSuccessResult.md @@ -3,7 +3,7 @@ id: QueryObserverSuccessResult title: QueryObserverSuccessResult --- -Defined in: [packages/query-core/src/types.ts:1017](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1017) +Defined in: packages/query-core/dist-ts/src/types.d.ts:587 ## Extends @@ -30,7 +30,7 @@ Defined in: [packages/query-core/src/types.ts:1017](https://github.com/TanStack/ | `errorUpdatedAt` | `number` | The timestamp for when the query most recently returned the `status` as `"error"`. | - | | `failureCount` | `number` | The failure count for the query. - Incremented every time the query fails. - Reset to `0` when the query succeeds. | - | | `failureReason` | `TError` \| `null` | The failure reason for the query retry. - Reset to `null` when the query succeeds. | - | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. - `paused`: The query wanted to fetch, but has been `paused`. - `idle`: The query is not fetching. - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | - | | `isEnabled` | `boolean` | `true` if this observer is enabled, `false` otherwise. | - | | `isError` | `false` | A derived boolean from the `status` variable, provided for convenience. - `true` if the query attempt resulted in an error. | [`QueryObserverBaseResult`](QueryObserverBaseResult.md).[`isError`](QueryObserverBaseResult.md#iserror) | | `isFetched` | `boolean` | Will be `true` if the query has been fetched. | - | diff --git a/docs/framework/angular/reference/interfaces/QueryOptions.md b/docs/framework/angular/reference/interfaces/QueryOptions.md index 2dbbbc1bda0..84f6e072b1d 100644 --- a/docs/framework/angular/reference/interfaces/QueryOptions.md +++ b/docs/framework/angular/reference/interfaces/QueryOptions.md @@ -3,7 +3,7 @@ id: QueryOptions title: QueryOptions --- -Defined in: [packages/query-core/src/types.ts:278](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L278) +Defined in: packages/query-core/dist-ts/src/types.d.ts:86 ## Type Parameters @@ -29,19 +29,19 @@ Defined in: [packages/query-core/src/types.ts:278](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `gcTime?` | `number` | `undefined` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | -| `initialData?` | `TData` \| () => `TData` \| `undefined` | `undefined` | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | -| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | -| `maxPages?` | `number` | `undefined` | Maximum number of pages to store in the data of an infinite query. | -| `meta?` | `Record`\<`string`, `unknown`\> | `undefined` | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | -| `networkMode?` | `"online"` \| `"always"` \| `"offlineFirst"` | `'online'` | Controls whether a query is allowed to run based on the current network connectivity. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | -| `persister?` | (`queryFn`: (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`NoInfer`\<`TQueryKey`\>, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\>, `context`: `object`, `query`: [`Query`](../classes/Query.md)) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> | `undefined` | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | -| `queryFn?` | \| (`context`: [`QueryFunctionContext`](../type-aliases/QueryFunctionContext.md)\<`TQueryKey`, `TPageParam`\>) => `TQueryFnData` \| `Promise`\<`TQueryFnData`\> \| *typeof* [`skipToken`](../variables/skipToken.md) | `undefined` | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | -| `queryHash?` | `string` | `undefined` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | -| `queryKey?` | `TQueryKey` | `undefined` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | -| `queryKeyHashFn?` | (`queryKey`: `TQueryKey`) => `string` | `undefined` | If specified, this function is used to hash the `queryKey` to a string. | -| `retry?` | \| `number` \| `false` \| `true` \| (`failureCount`: `number`, `error`: `TError`) => `boolean` | `undefined` | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | -| `retryDelay?` | `number` \| (`failureCount`: `number`, `error`: `TError`) => `number` | `undefined` | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | -| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | `true` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. | +| Property | Type | Description | +| ------ | ------ | ------ | +| `gcTime?` | `number` | The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used. Setting it to `Infinity` will disable garbage collection. Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a workaround. | +| `initialData?` | \| `TData` \| [`InitialDataFunction`](../type-aliases/InitialDataFunction.md)\<`TData`\> | If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet). If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initial data. Initial data is considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the cache. | +| `initialDataUpdatedAt?` | `number` \| () => `number` \| `undefined` | If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. | +| `maxPages?` | `number` | Maximum number of pages to store in the data of an infinite query. | +| `meta?` | `Record`\<`string`, `unknown`\> | Additional payload to be stored on each query. Use this property to pass information that can be used in other places. | +| `networkMode?` | [`NetworkMode`](../type-aliases/NetworkMode.md) | Controls whether a query is allowed to run based on the current network connectivity. Defaults to `'online'`. **See** [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. | +| `persister?` | [`QueryPersister`](../type-aliases/QueryPersister.md)\<`TQueryFnData`, `NoInfer`\<`TQueryKey`\>, `TPageParam`\> | This option can be used to persist the result of a query to an external storage, bypassing the need to actually call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. | +| `queryFn?` | \| [`QueryFunction`](../type-aliases/QueryFunction.md)\<`TQueryFnData`, `TQueryKey`, `TPageParam`\> \| *typeof* [`skipToken`](../variables/skipToken.md) | The function that the query will use to request data. Required, unless a default query function has been set via `queryClient.setQueryDefaults` or `queryClient.setDefaultOptions`. Receives a [QueryFunctionContext](../type-aliases/QueryFunctionContext.md). Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. | +| `queryHash?` | `string` | The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used as the actual cache key internally. | +| `queryKey?` | `TQueryKey` | The query key to use for this query. The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information. The query will automatically update when this key changes (as long as `enabled` is not set to `false`). | +| `queryKeyHashFn?` | [`QueryKeyHashFunction`](../type-aliases/QueryKeyHashFunction.md)\<`TQueryKey`\> | If specified, this function is used to hash the `queryKey` to a string. | +| `retry?` | `RetryValue`\<`TError`\> | If `false`, failed queries will not retry by default. If `true`, failed queries will retry infinitely. If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. Defaults to `3` on the client and `0` on the server. | +| `retryDelay?` | `RetryDelayValue`\<`TError`\> | This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds. A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. A function like `attempt => attempt * 1000` applies linear backoff. Defaults to a function that applies exponential backoff, capped at 30 seconds. | +| `structuralSharing?` | `boolean` \| (`oldData`: `unknown`, `newData`: `unknown`) => `unknown` | Set this to `false` to disable structural sharing between query results. Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. Defaults to `true`. | diff --git a/docs/framework/angular/reference/interfaces/QueryResource.md b/docs/framework/angular/reference/interfaces/QueryResource.md index dbfe89d3e72..ed538b99aac 100644 --- a/docs/framework/angular/reference/interfaces/QueryResource.md +++ b/docs/framework/angular/reference/interfaces/QueryResource.md @@ -17,109 +17,14 @@ Defined in: [packages/angular-query/src/query-resource.ts:6](https://github.com/ ## Properties -### error - -```ts -readonly error: Signal; -``` - -Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:139 - -When in the `error` state, this returns the last known error from the `Resource`. - -#### Inherited from - -```ts -Resource.error -``` - -*** - -### isLoading - -```ts -readonly isLoading: Signal; -``` - -Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:143 - -Whether this resource is loading a new value (or reloading the existing one). - -#### Inherited from - -```ts -Resource.isLoading -``` - -*** - -### reload() - -```ts -reload: () => boolean; -``` - -Defined in: [packages/angular-query/src/query-resource.ts:20](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-resource.ts#L20) - -Requests a new query fetch only when the current query data is stale. - -Used for compatibility with Angular APIs that might want to reload a resource, -like Signal Forms' validateAsync resource interface. - -#### Returns - -`boolean` - -`true` if a reload was initiated, `false` if a reload was unnecessary or unsupported. - -*** - -### snapshot - -```ts -readonly snapshot: Signal>; -``` - -Defined in: [packages/angular-query/src/query-resource.ts:10](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-resource.ts#L10) - -The current query state as a single snapshot. - -*** - -### status - -```ts -readonly status: Signal; -``` - -Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:135 - -The current status of the `Resource`, which describes what the resource is currently doing and -what can be expected of its `value`. - -#### Inherited from - -```ts -Resource.status -``` - -*** - -### value - -```ts -readonly value: Signal; -``` - -Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:130 - -The current value of the `Resource`, or throws an error if the resource is in an error state. - -#### Inherited from - -```ts -Resource.value -``` +| Property | Modifier | Type | Description | Overrides | +| ------ | ------ | ------ | ------ | ------ | +| `error` | `readonly` | `Signal`\<`Error` \| `undefined`\> | When in the `error` state, this returns the last known error from the `Resource`. | - | +| `isLoading` | `readonly` | `Signal`\<`boolean`\> | Whether this resource is loading a new value (or reloading the existing one). | - | +| `reload` | `public` | () => `boolean` | Requests a new query fetch only when the current query data is stale. Used for compatibility with Angular APIs that might want to reload a resource, like Signal Forms' validateAsync resource interface. | - | +| `snapshot` | `readonly` | `Signal`\<`ResourceSnapshot`\<`TValue`\>\> | The current query state as a single snapshot. | `Resource.snapshot` | +| `status` | `readonly` | `Signal`\<`ResourceStatus`\> | The current status of the `Resource`, which describes what the resource is currently doing and what can be expected of its `value`. | - | +| `value` | `readonly` | `Signal`\<`TValue`\> | The current value of the `Resource`, or throws an error if the resource is in an error state. | - | ## Methods @@ -128,10 +33,10 @@ Resource.value #### Call Signature ```ts -hasValue(this): this is Resource>; +hasValue(this: TValue extends undefined ? QueryResource : never): this is Resource>; ``` -Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:149 +Defined in: node\_modules/.pnpm/@angular+core@22.1.6\_@angular+compiler@22.1.6\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/types/\_api-chunk.d.ts:186 Whether this resource has a valid current value. @@ -159,7 +64,7 @@ Resource.hasValue hasValue(): boolean; ``` -Defined in: node\_modules/.pnpm/@angular+core@20.3.18\_@angular+compiler@20.3.18\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/api.d.d.ts:150 +Defined in: node\_modules/.pnpm/@angular+core@22.1.6\_@angular+compiler@22.1.6\_rxjs@7.8.2\_zone.js@0.16.1/node\_modules/@angular/core/types/\_api-chunk.d.ts:187 ##### Returns diff --git a/docs/framework/angular/reference/interfaces/QueryState.md b/docs/framework/angular/reference/interfaces/QueryState.md index 131d202908d..06af2724a2f 100644 --- a/docs/framework/angular/reference/interfaces/QueryState.md +++ b/docs/framework/angular/reference/interfaces/QueryState.md @@ -3,7 +3,7 @@ id: QueryState title: QueryState --- -Defined in: [packages/query-core/src/query.ts:52](https://github.com/TanStack/query/blob/main/packages/query-core/src/query.ts#L52) +Defined in: packages/query-core/dist-ts/src/query.d.ts:17 The raw state stored on a `Query` instance. This is the underlying state that observer results (e.g. `QueryObserverResult`) are derived from. @@ -31,6 +31,6 @@ that observer results (e.g. `QueryObserverResult`) are derived from. | `fetchFailureCount` | `number` | The failure count for the current fetch. - Incremented every time the fetch fails. - Reset to `0` when the fetch succeeds. | | `fetchFailureReason` | `TError` \| `null` | The reason the current fetch failed, as reported by the retryer. - Reset to `null` when the fetch succeeds. | | `fetchMeta` | `FetchMeta` \| `null` | Metadata passed to the currently in-flight (or most recent) fetch, e.g. the `fetchMore` direction for infinite queries. | -| `fetchStatus` | `"fetching"` \| `"paused"` \| `"idle"` | The fetch status of the query. - `fetching`: the `queryFn` is currently executing. - `paused`: a fetch wanted to run but has been paused (see network mode). - `idle`: the query is not fetching. | +| `fetchStatus` | [`FetchStatus`](../type-aliases/FetchStatus.md) | The fetch status of the query. - `fetching`: the `queryFn` is currently executing. - `paused`: a fetch wanted to run but has been paused (see network mode). - `idle`: the query is not fetching. | | `isInvalidated` | `boolean` | Whether the query has been marked as invalidated via `invalidate()`. - Reset to `false` whenever the query resolves successfully. | -| `status` | `"error"` \| `"pending"` \| `"success"` | The status of the query. - `pending` if there's no cached data and no attempt was finished yet. - `error` if the last attempt resulted in an error. - `success` if the query has data. | +| `status` | [`QueryStatus`](../type-aliases/QueryStatus.md) | The status of the query. - `pending` if there's no cached data and no attempt was finished yet. - `error` if the last attempt resulted in an error. - `success` if the query has data. | diff --git a/docs/framework/angular/reference/interfaces/RefetchOptions.md b/docs/framework/angular/reference/interfaces/RefetchOptions.md index 0fdd089798b..e8e02795db0 100644 --- a/docs/framework/angular/reference/interfaces/RefetchOptions.md +++ b/docs/framework/angular/reference/interfaces/RefetchOptions.md @@ -3,7 +3,7 @@ id: RefetchOptions title: RefetchOptions --- -Defined in: [packages/query-core/src/types.ts:763](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L763) +Defined in: packages/query-core/dist-ts/src/types.d.ts:366 ## Extends @@ -16,7 +16,7 @@ Defined in: [packages/query-core/src/types.ts:763](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `cancelRefetch?` | `boolean` | `true` | If set to `true`, a currently running request will be cancelled before a new request is made If set to `false`, no refetch will be made if there is already a request running. | -| `throwOnError?` | `boolean` | `false` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. If set to `false`, failed refetches are swallowed and not surfaced to the caller. | +| Property | Type | Description | +| ------ | ------ | ------ | +| `cancelRefetch?` | `boolean` | If set to `true`, a currently running request will be cancelled before a new request is made If set to `false`, no refetch will be made if there is already a request running. Defaults to `true`. | +| `throwOnError?` | `boolean` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. Defaults to `false`, in which case failed refetches are swallowed and not surfaced to the caller. | diff --git a/docs/framework/angular/reference/interfaces/RefetchQueryFilters.md b/docs/framework/angular/reference/interfaces/RefetchQueryFilters.md index b65718981c3..171ee7a0d76 100644 --- a/docs/framework/angular/reference/interfaces/RefetchQueryFilters.md +++ b/docs/framework/angular/reference/interfaces/RefetchQueryFilters.md @@ -3,7 +3,7 @@ id: RefetchQueryFilters title: RefetchQueryFilters --- -Defined in: [packages/query-core/src/types.ts:790](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L790) +Defined in: packages/query-core/dist-ts/src/types.d.ts:388 Filters used to select queries, for example in `queryClient.getQueriesData` or `queryClient.invalidateQueries`. All provided filters must match; filters that are left unspecified are ignored. @@ -20,11 +20,11 @@ All provided filters must match; filters that are left unspecified are ignored. ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `exact?` | `boolean` | `undefined` | Match query key exactly | -| `fetchStatus?` | `"fetching"` \| `"paused"` \| `"idle"` | `undefined` | Include queries matching their fetchStatus | -| `predicate?` | (`query`: [`Query`](../classes/Query.md)) => `boolean` | `undefined` | Include queries matching this predicate function | -| `queryKey?` | `TQueryKey` \| `TuplePrefixes`\<`TQueryKey`\> | `undefined` | Include queries matching this query key | -| `stale?` | `boolean` | `undefined` | Include or exclude stale queries | -| `type?` | `QueryTypeFilter` | `'all'` | Filter to active queries, inactive queries or all queries | +| Property | Type | Description | +| ------ | ------ | ------ | +| `exact?` | `boolean` | Match query key exactly | +| `fetchStatus?` | [`FetchStatus`](../type-aliases/FetchStatus.md) | Include queries matching their fetchStatus | +| `predicate?` | (`query`: [`Query`](../classes/Query.md)) => `boolean` | Include queries matching this predicate function | +| `queryKey?` | `TQueryKey` \| `TuplePrefixes`\<`TQueryKey`\> | Include queries matching this query key | +| `stale?` | `boolean` | Include or exclude stale queries | +| `type?` | `QueryTypeFilter` | Filter to active queries, inactive queries or all queries Defaults to `'all'`. | diff --git a/docs/framework/angular/reference/interfaces/Register.md b/docs/framework/angular/reference/interfaces/Register.md index 3670e1d1599..68e892cf726 100644 --- a/docs/framework/angular/reference/interfaces/Register.md +++ b/docs/framework/angular/reference/interfaces/Register.md @@ -3,24 +3,4 @@ id: Register title: Register --- -Defined in: [packages/query-core/src/types.ts:56](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L56) - -The interface to augment via declaration merging to override Query's default types repository-wide. -Each field it declares replaces the default of the matching type: `defaultError` for [DefaultError](../type-aliases/DefaultError.md), -`queryKey` for [QueryKey](../type-aliases/QueryKey.md), `mutationKey` for [MutationKey](../type-aliases/MutationKey.md), `queryMeta` for [QueryMeta](../type-aliases/QueryMeta.md) and -`mutationMeta` for [MutationMeta](../type-aliases/MutationMeta.md). Leave a field out to keep that type's default. -Augment the module you install — `@tanstack/react-query`, `@tanstack/vue-query`, -`@tanstack/solid-query`, `@tanstack/svelte-query`, `@tanstack/preact-query`, -`@tanstack/angular-query-experimental` or `@tanstack/lit-query`. Augmenting `@tanstack/query-core` -works too and covers every adapter at once. - -## Example - -```ts -// Use the module you installed — here, the React adapter. -declare module '@tanstack/react-query' { - interface Register { - defaultError: AxiosError - } -} -``` +Defined in: packages/query-core/dist-ts/src/types.d.ts:15 diff --git a/docs/framework/angular/reference/interfaces/ResetOptions.md b/docs/framework/angular/reference/interfaces/ResetOptions.md index 763e4c32052..31d605a122c 100644 --- a/docs/framework/angular/reference/interfaces/ResetOptions.md +++ b/docs/framework/angular/reference/interfaces/ResetOptions.md @@ -3,7 +3,7 @@ id: ResetOptions title: ResetOptions --- -Defined in: [packages/query-core/src/types.ts:795](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L795) +Defined in: packages/query-core/dist-ts/src/types.d.ts:392 ## Extends @@ -11,7 +11,7 @@ Defined in: [packages/query-core/src/types.ts:795](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `cancelRefetch?` | `boolean` | `true` | If set to `true`, a currently running request will be cancelled before a new request is made If set to `false`, no refetch will be made if there is already a request running. | -| `throwOnError?` | `boolean` | `false` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. If set to `false`, failed refetches are swallowed and not surfaced to the caller. | +| Property | Type | Description | +| ------ | ------ | ------ | +| `cancelRefetch?` | `boolean` | If set to `true`, a currently running request will be cancelled before a new request is made If set to `false`, no refetch will be made if there is already a request running. Defaults to `true`. | +| `throwOnError?` | `boolean` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. Defaults to `false`, in which case failed refetches are swallowed and not surfaced to the caller. | diff --git a/docs/framework/angular/reference/interfaces/ResultOptions.md b/docs/framework/angular/reference/interfaces/ResultOptions.md index f90ce92977b..47c983b7596 100644 --- a/docs/framework/angular/reference/interfaces/ResultOptions.md +++ b/docs/framework/angular/reference/interfaces/ResultOptions.md @@ -3,7 +3,7 @@ id: ResultOptions title: ResultOptions --- -Defined in: [packages/query-core/src/types.ts:753](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L753) +Defined in: packages/query-core/dist-ts/src/types.d.ts:357 ## Extended by @@ -13,6 +13,6 @@ Defined in: [packages/query-core/src/types.ts:753](https://github.com/TanStack/q ## Properties -| Property | Type | Default value | Description | -| ------ | ------ | ------ | ------ | -| `throwOnError?` | `boolean` | `false` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. If set to `false`, failed refetches are swallowed and not surfaced to the caller. | +| Property | Type | Description | +| ------ | ------ | ------ | +| `throwOnError?` | `boolean` | If set to `true`, the method throws if any of the underlying query refetch tasks fail. Defaults to `false`, in which case failed refetches are swallowed and not surfaced to the caller. | diff --git a/docs/framework/angular/reference/interfaces/SetDataOptions.md b/docs/framework/angular/reference/interfaces/SetDataOptions.md index 9fa988ea92d..74b7dce3a9f 100644 --- a/docs/framework/angular/reference/interfaces/SetDataOptions.md +++ b/docs/framework/angular/reference/interfaces/SetDataOptions.md @@ -3,11 +3,7 @@ id: SetDataOptions title: SetDataOptions --- -Defined in: [packages/query-core/src/types.ts:1655](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1655) - -Options for writing data into the cache, e.g. via `queryClient.setQueryData()`. -`updatedAt` overrides the timestamp the data is recorded with, which is what staleness is measured from; -omit it to use the current time. +Defined in: packages/query-core/dist-ts/src/types.d.ts:937 ## Properties diff --git a/docs/framework/angular/reference/interfaces/TimeoutManager.md b/docs/framework/angular/reference/interfaces/TimeoutManager.md index 317213619d5..0ab433b9780 100644 --- a/docs/framework/angular/reference/interfaces/TimeoutManager.md +++ b/docs/framework/angular/reference/interfaces/TimeoutManager.md @@ -3,7 +3,7 @@ id: TimeoutManager title: TimeoutManager --- -Defined in: [packages/query-core/src/timeoutManager.ts:70](https://github.com/TanStack/query/blob/main/packages/query-core/src/timeoutManager.ts#L70) +Defined in: packages/query-core/dist-ts/src/timeoutManager.d.ts:46 Allows customization of how timeouts are created. @@ -27,7 +27,7 @@ coalesces timeouts. clearInterval(intervalId: ManagedTimerId | undefined): void; ``` -Defined in: [packages/query-core/src/timeoutManager.ts:224](https://github.com/TanStack/query/blob/main/packages/query-core/src/timeoutManager.ts#L224) +Defined in: packages/query-core/dist-ts/src/timeoutManager.d.ts:148 `clearInterval` can be used to cancel an interval, like the global `clearInterval` function. It should be called with an interval ID @@ -68,7 +68,7 @@ timeoutManager.clearInterval(intervalId) clearTimeout(timeoutId: ManagedTimerId | undefined): void; ``` -Defined in: [packages/query-core/src/timeoutManager.ts:179](https://github.com/TanStack/query/blob/main/packages/query-core/src/timeoutManager.ts#L179) +Defined in: packages/query-core/dist-ts/src/timeoutManager.d.ts:112 `clearTimeout` cancels a timeout callback scheduled with `setTimeout`, like the global `clearTimeout` function. It should be called with a @@ -109,7 +109,7 @@ timeoutManager.clearTimeout(timeoutId) setInterval(callback: TimeoutCallback, delay: number): ManagedTimerId; ``` -Defined in: [packages/query-core/src/timeoutManager.ts:200](https://github.com/TanStack/query/blob/main/packages/query-core/src/timeoutManager.ts#L200) +Defined in: packages/query-core/dist-ts/src/timeoutManager.d.ts:130 `setInterval` schedules a callback to be called approximately every `delay` milliseconds, like the global `setInterval` function. @@ -154,7 +154,7 @@ const intervalId = timeoutManager.setInterval( setTimeout(callback: TimeoutCallback, delay: number): ManagedTimerId; ``` -Defined in: [packages/query-core/src/timeoutManager.ts:155](https://github.com/TanStack/query/blob/main/packages/query-core/src/timeoutManager.ts#L155) +Defined in: packages/query-core/dist-ts/src/timeoutManager.d.ts:94 `setTimeout` schedules a callback to run after approximately `delay` milliseconds, like the global `setTimeout` function. The callback can be @@ -202,7 +202,7 @@ const timeoutIdNumber: number = Number(timeoutId) setTimeoutProvider(provider: TimeoutProvider): void; ``` -Defined in: [packages/query-core/src/timeoutManager.ts:106](https://github.com/TanStack/query/blob/main/packages/query-core/src/timeoutManager.ts#L106) +Defined in: packages/query-core/dist-ts/src/timeoutManager.d.ts:73 `setTimeoutProvider` can be used to set a custom implementation of the `setTimeout`, `clearTimeout`, `setInterval`, `clearInterval` functions, diff --git a/docs/framework/angular/reference/type-aliases/AnyDataTag.md b/docs/framework/angular/reference/type-aliases/AnyDataTag.md index 2b1f57e75e7..debdf20e327 100644 --- a/docs/framework/angular/reference/type-aliases/AnyDataTag.md +++ b/docs/framework/angular/reference/type-aliases/AnyDataTag.md @@ -7,7 +7,7 @@ title: AnyDataTag type AnyDataTag = object; ``` -Defined in: [packages/query-core/src/types.ts:94](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L94) +Defined in: packages/query-core/dist-ts/src/types.d.ts:29 ## Properties diff --git a/docs/framework/angular/reference/type-aliases/CreateBaseMutationResult.md b/docs/framework/angular/reference/type-aliases/CreateBaseMutationResult.md index bc7ffa49731..7b962c1a0f0 100644 --- a/docs/framework/angular/reference/type-aliases/CreateBaseMutationResult.md +++ b/docs/framework/angular/reference/type-aliases/CreateBaseMutationResult.md @@ -9,7 +9,11 @@ type CreateBaseMutationResult = Over }> & object; ``` -Defined in: [packages/angular-query/src/types.ts:269](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L269) +Defined in: [packages/angular-query/src/types.ts:355](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L355) + +The pre-`Signal` shape [CreateMutationResult](CreateMutationResult.md) is built from — not what `injectMutation` actually +returns. Same as [MutationObserverResult](MutationObserverResult.md) from `@tanstack/query-core`, with `mutate` narrowed to the +fire-and-forget [CreateMutateFunction](CreateMutateFunction.md) signature, plus the added `mutateAsync`. ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/CreateBaseQueryResult.md b/docs/framework/angular/reference/type-aliases/CreateBaseQueryResult.md index def30c80476..4648fc4a70a 100644 --- a/docs/framework/angular/reference/type-aliases/CreateBaseQueryResult.md +++ b/docs/framework/angular/reference/type-aliases/CreateBaseQueryResult.md @@ -4,10 +4,17 @@ title: CreateBaseQueryResult --- ```ts -type CreateBaseQueryResult = BaseQueryNarrowing & MapToSignals, MethodKeys>>; +type CreateBaseQueryResult = BaseQueryNarrowing & MapToSignals, QueryResultFields>; ``` -Defined in: [packages/angular-query/src/types.ts:191](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L191) +Defined in: [packages/angular-query/src/types.ts:207](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L207) + +The result of `injectQuery` when `initialData` isn't set — `data` may be `undefined` while the query is +`pending`. Same shape as [QueryObserverResult](QueryObserverResult.md) from `@tanstack/query-core`, but value fields (like +`data`, `error`, `status`) are exposed as a `Signal` — read them with `query.data()`, not `query.data` — +while function fields (like `refetch`) are called directly, unchanged. `isSuccess`/`isError`/`isPending` +are [BaseQueryNarrowing](../interfaces/BaseQueryNarrowing.md) type-guard methods rather than plain booleans. +`injectInfiniteQuery` returns [CreateInfiniteQueryResult](CreateInfiniteQueryResult.md) instead. ## Type Parameters @@ -25,4 +32,4 @@ The type of errors your `queryFn` may throw. ### TState -`TState` *extends* `QueryObserverResult`\<`TData`, `TError`\> = `QueryObserverResult`\<`TData`, `TError`\> +`TState` *extends* [`QueryObserverResult`](QueryObserverResult.md)\<`TData`, `TError`\> = [`QueryObserverResult`](QueryObserverResult.md)\<`TData`, `TError`\> diff --git a/docs/framework/angular/reference/type-aliases/CreateInfiniteQueryResult.md b/docs/framework/angular/reference/type-aliases/CreateInfiniteQueryResult.md index c09f572f8de..fbdd53bc95b 100644 --- a/docs/framework/angular/reference/type-aliases/CreateInfiniteQueryResult.md +++ b/docs/framework/angular/reference/type-aliases/CreateInfiniteQueryResult.md @@ -4,10 +4,15 @@ title: CreateInfiniteQueryResult --- ```ts -type CreateInfiniteQueryResult = BaseInfiniteQueryNarrowing & MapToSignals>; +type CreateInfiniteQueryResult = BaseInfiniteQueryNarrowing & MapToSignals; ``` -Defined in: [packages/angular-query/src/types.ts:220](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L220) +Defined in: [packages/angular-query/src/types.ts:259](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L259) + +The result of `injectInfiniteQuery` when `initialData` isn't set — `data` may be `undefined` while the +query is `pending`. Same shape as [InfiniteQueryObserverResult](InfiniteQueryObserverResult.md) from `@tanstack/query-core`, but +value fields are exposed as a `Signal` while function fields (like `fetchNextPage`) are called directly, +unchanged. ## Type Parameters @@ -19,8 +24,10 @@ The type `data` ends up as after `select` runs. ### TError -`TError` = `DefaultError` +`TError` = [`DefaultError`](DefaultError.md) + +The type of errors your `queryFn` may throw. ### TState -`TState` *extends* `InfiniteQueryObserverResult`\<`TData`, `TError`\> = `InfiniteQueryObserverResult`\<`TData`, `TError`\> +`TState` *extends* [`InfiniteQueryObserverResult`](InfiniteQueryObserverResult.md)\<`TData`, `TError`\> = [`InfiniteQueryObserverResult`](InfiniteQueryObserverResult.md)\<`TData`, `TError`\> diff --git a/docs/framework/angular/reference/type-aliases/CreateMutateAsyncFunction.md b/docs/framework/angular/reference/type-aliases/CreateMutateAsyncFunction.md index 2d410fe52f6..4ec6e48ec99 100644 --- a/docs/framework/angular/reference/type-aliases/CreateMutateAsyncFunction.md +++ b/docs/framework/angular/reference/type-aliases/CreateMutateAsyncFunction.md @@ -7,7 +7,10 @@ title: CreateMutateAsyncFunction type CreateMutateAsyncFunction = MutateFunction; ``` -Defined in: [packages/angular-query/src/types.ts:262](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L262) +Defined in: [packages/angular-query/src/types.ts:337](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L337) + +The type of `mutateAsync`, as returned by `injectMutation`. Similar to [CreateMutateFunction](CreateMutateFunction.md), but +returns a promise which can be awaited. ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/CreateMutateFunction.md b/docs/framework/angular/reference/type-aliases/CreateMutateFunction.md index 2e939f7ccd3..ef809812745 100644 --- a/docs/framework/angular/reference/type-aliases/CreateMutateFunction.md +++ b/docs/framework/angular/reference/type-aliases/CreateMutateFunction.md @@ -7,7 +7,11 @@ title: CreateMutateFunction type CreateMutateFunction = (...args: Parameters>) => void; ``` -Defined in: [packages/angular-query/src/types.ts:251](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L251) +Defined in: [packages/angular-query/src/types.ts:316](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L316) + +The type of `mutate`, as returned by `injectMutation`. Forwards the variables (and an optional per-call +`onSuccess`/`onError`/`onSettled`) to the underlying `mutate` call. Fire-and-forget — errors are surfaced +through the mutation result, not thrown. ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/CreateMutationResult.md b/docs/framework/angular/reference/type-aliases/CreateMutationResult.md index d46f090d102..67584e84ab9 100644 --- a/docs/framework/angular/reference/type-aliases/CreateMutationResult.md +++ b/docs/framework/angular/reference/type-aliases/CreateMutationResult.md @@ -4,10 +4,15 @@ title: CreateMutationResult --- ```ts -type CreateMutationResult = BaseMutationNarrowing & MapToSignals, MethodKeys>>; +type CreateMutationResult = BaseMutationNarrowing & MapToSignals, MutationResultFields>; ``` -Defined in: [packages/angular-query/src/types.ts:373](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L373) +Defined in: [packages/angular-query/src/types.ts:474](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L474) + +The result of `injectMutation`. Based on [CreateBaseMutationResult](CreateBaseMutationResult.md), but value fields are exposed as +a `Signal` — read them with `mutation.data()`, not `mutation.data` — while function fields (`mutate`, +`mutateAsync`, `reset`) are called directly, unchanged. `isSuccess`/`isError`/`isPending`/`isIdle` are +[BaseMutationNarrowing](../interfaces/BaseMutationNarrowing.md) type-guard methods rather than plain booleans. ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/CreateQueryOptions.md b/docs/framework/angular/reference/type-aliases/CreateQueryOptions.md index f71513d7083..361ad4cad25 100644 --- a/docs/framework/angular/reference/type-aliases/CreateQueryOptions.md +++ b/docs/framework/angular/reference/type-aliases/CreateQueryOptions.md @@ -7,7 +7,7 @@ title: CreateQueryOptions type CreateQueryOptions = OmitKeyof, "notifyOnChangeProps" | "suspense" | "throwOnError">; ``` -Defined in: [packages/angular-query/src/types.ts:23](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L23) +Defined in: [packages/angular-query/src/types.ts:28](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L28) ## Type Parameters @@ -17,7 +17,7 @@ Defined in: [packages/angular-query/src/types.ts:23](https://github.com/TanStack ### TError -`TError` = `DefaultError` +`TError` = [`DefaultError`](DefaultError.md) ### TData @@ -25,4 +25,4 @@ Defined in: [packages/angular-query/src/types.ts:23](https://github.com/TanStack ### TQueryKey -`TQueryKey` *extends* `QueryKey` = `QueryKey` +`TQueryKey` *extends* [`QueryKey`](QueryKey.md) = [`QueryKey`](QueryKey.md) diff --git a/docs/framework/angular/reference/type-aliases/CreateQueryResult.md b/docs/framework/angular/reference/type-aliases/CreateQueryResult.md index c289489f1d9..2fcd5cea8b8 100644 --- a/docs/framework/angular/reference/type-aliases/CreateQueryResult.md +++ b/docs/framework/angular/reference/type-aliases/CreateQueryResult.md @@ -7,7 +7,9 @@ title: CreateQueryResult type CreateQueryResult = CreateBaseQueryResult; ``` -Defined in: [packages/angular-query/src/types.ts:204](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L204) +Defined in: [packages/angular-query/src/types.ts:226](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L226) + +The result of `injectQuery`. Same as [CreateBaseQueryResult](CreateBaseQueryResult.md). ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/DataTag.md b/docs/framework/angular/reference/type-aliases/DataTag.md index 92b59fc9651..625108004be 100644 --- a/docs/framework/angular/reference/type-aliases/DataTag.md +++ b/docs/framework/angular/reference/type-aliases/DataTag.md @@ -7,7 +7,7 @@ title: DataTag type DataTag = TType extends AnyDataTag ? TType : TType & object; ``` -Defined in: [packages/query-core/src/types.ts:98](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L98) +Defined in: packages/query-core/dist-ts/src/types.d.ts:33 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/DefaultError.md b/docs/framework/angular/reference/type-aliases/DefaultError.md index 1b6571b9a25..470a0cbe9b7 100644 --- a/docs/framework/angular/reference/type-aliases/DefaultError.md +++ b/docs/framework/angular/reference/type-aliases/DefaultError.md @@ -7,7 +7,4 @@ title: DefaultError type DefaultError = Register extends object ? TError : Error; ``` -Defined in: [packages/query-core/src/types.ts:68](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L68) - -The error type used wherever an error is not given an explicit type parameter. -Defaults to `Error`; declare `defaultError` on [Register](../interfaces/Register.md) to change it everywhere at once. +Defined in: packages/query-core/dist-ts/src/types.d.ts:17 diff --git a/docs/framework/angular/reference/type-aliases/DefaultedInfiniteQueryObserverOptions.md b/docs/framework/angular/reference/type-aliases/DefaultedInfiniteQueryObserverOptions.md index fc8fcb9cd5f..5c91200fa50 100644 --- a/docs/framework/angular/reference/type-aliases/DefaultedInfiniteQueryObserverOptions.md +++ b/docs/framework/angular/reference/type-aliases/DefaultedInfiniteQueryObserverOptions.md @@ -7,7 +7,7 @@ title: DefaultedInfiniteQueryObserverOptions type DefaultedInfiniteQueryObserverOptions = WithRequired, "throwOnError" | "refetchOnReconnect" | "queryHash">; ``` -Defined in: [packages/query-core/src/types.ts:612](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L612) +Defined in: packages/query-core/dist-ts/src/types.d.ts:321 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/DefaultedQueryObserverOptions.md b/docs/framework/angular/reference/type-aliases/DefaultedQueryObserverOptions.md index e1ba93f3f14..c61a9185b1c 100644 --- a/docs/framework/angular/reference/type-aliases/DefaultedQueryObserverOptions.md +++ b/docs/framework/angular/reference/type-aliases/DefaultedQueryObserverOptions.md @@ -7,7 +7,7 @@ title: DefaultedQueryObserverOptions type DefaultedQueryObserverOptions = WithRequired, "throwOnError" | "refetchOnReconnect" | "queryHash">; ``` -Defined in: [packages/query-core/src/types.ts:583](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L583) +Defined in: packages/query-core/dist-ts/src/types.d.ts:318 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/DefinedCreateInfiniteQueryResult.md b/docs/framework/angular/reference/type-aliases/DefinedCreateInfiniteQueryResult.md index c45e90f217e..e5aeb4b3902 100644 --- a/docs/framework/angular/reference/type-aliases/DefinedCreateInfiniteQueryResult.md +++ b/docs/framework/angular/reference/type-aliases/DefinedCreateInfiniteQueryResult.md @@ -4,10 +4,14 @@ title: DefinedCreateInfiniteQueryResult --- ```ts -type DefinedCreateInfiniteQueryResult = DefinedInfiniteQueryNarrowing & MapToSignals>; +type DefinedCreateInfiniteQueryResult = DefinedInfiniteQueryNarrowing & MapToSignals; ``` -Defined in: [packages/angular-query/src/types.ts:228](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L228) +Defined in: [packages/angular-query/src/types.ts:275](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L275) + +The result of `injectInfiniteQuery` when `initialData` is set — `data` is never `undefined`. Same shape as +[DefinedInfiniteQueryObserverResult](DefinedInfiniteQueryObserverResult.md) from `@tanstack/query-core`, but value fields are exposed as a +`Signal` while function fields are called directly, unchanged. ## Type Parameters @@ -25,4 +29,4 @@ The type of errors your `queryFn` may throw. ### TDefinedInfiniteQueryObserver -`TDefinedInfiniteQueryObserver` *extends* `DefinedInfiniteQueryObserverResult`\<`TData`, `TError`\> = `DefinedInfiniteQueryObserverResult`\<`TData`, `TError`\> +`TDefinedInfiniteQueryObserver` *extends* [`DefinedInfiniteQueryObserverResult`](DefinedInfiniteQueryObserverResult.md)\<`TData`, `TError`\> = [`DefinedInfiniteQueryObserverResult`](DefinedInfiniteQueryObserverResult.md)\<`TData`, `TError`\> diff --git a/docs/framework/angular/reference/type-aliases/DefinedCreateQueryResult.md b/docs/framework/angular/reference/type-aliases/DefinedCreateQueryResult.md index fbeae6470c5..19428c25bde 100644 --- a/docs/framework/angular/reference/type-aliases/DefinedCreateQueryResult.md +++ b/docs/framework/angular/reference/type-aliases/DefinedCreateQueryResult.md @@ -4,10 +4,14 @@ title: DefinedCreateQueryResult --- ```ts -type DefinedCreateQueryResult = DefinedQueryNarrowing & MapToSignals, MethodKeys>>; +type DefinedCreateQueryResult = DefinedQueryNarrowing & MapToSignals, QueryResultFields>; ``` -Defined in: [packages/angular-query/src/types.ts:209](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L209) +Defined in: [packages/angular-query/src/types.ts:239](https://github.com/TanStack/query/blob/main/packages/angular-query/src/types.ts#L239) + +The result of `injectQuery` when `initialData` is set — `data` is never `undefined`. Same shape as +[DefinedQueryObserverResult](DefinedQueryObserverResult.md) from `@tanstack/query-core`, but value fields are exposed as a +`Signal` while function fields are called directly, unchanged. ## Type Parameters @@ -25,4 +29,4 @@ The type of errors your `queryFn` may throw. ### TState -`TState` *extends* `DefinedQueryObserverResult`\<`TData`, `TError`\> = `DefinedQueryObserverResult`\<`TData`, `TError`\> +`TState` *extends* [`DefinedQueryObserverResult`](DefinedQueryObserverResult.md)\<`TData`, `TError`\> = [`DefinedQueryObserverResult`](DefinedQueryObserverResult.md)\<`TData`, `TError`\> diff --git a/docs/framework/angular/reference/type-aliases/DefinedInfiniteQueryObserverResult.md b/docs/framework/angular/reference/type-aliases/DefinedInfiniteQueryObserverResult.md index 3449c1a6dc8..f07ca3aec0f 100644 --- a/docs/framework/angular/reference/type-aliases/DefinedInfiniteQueryObserverResult.md +++ b/docs/framework/angular/reference/type-aliases/DefinedInfiniteQueryObserverResult.md @@ -9,7 +9,7 @@ type DefinedInfiniteQueryObserverResult = | InfiniteQueryObserverSuccessResult; ``` -Defined in: [packages/query-core/src/types.ts:1210](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1210) +Defined in: packages/query-core/dist-ts/src/types.d.ts:728 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/DefinedInitialDataInfiniteOptions.md b/docs/framework/angular/reference/type-aliases/DefinedInitialDataInfiniteOptions.md index db4668bf7c8..a0c7563dee8 100644 --- a/docs/framework/angular/reference/type-aliases/DefinedInitialDataInfiniteOptions.md +++ b/docs/framework/angular/reference/type-aliases/DefinedInitialDataInfiniteOptions.md @@ -7,7 +7,10 @@ title: DefinedInitialDataInfiniteOptions type DefinedInitialDataInfiniteOptions = CreateInfiniteQueryOptions & object; ``` -Defined in: [packages/angular-query/src/infinite-query-options.ts:62](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L62) +Defined in: [packages/angular-query/src/infinite-query-options.ts:109](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L109) + +The options accepted by the `infiniteQueryOptions` overload selected when `initialData` is set — `data` is +never `undefined` (unless a `select` changes `TData` to include `undefined`). ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/DefinedInitialDataOptions.md b/docs/framework/angular/reference/type-aliases/DefinedInitialDataOptions.md index c301220238c..11ff2b1d60e 100644 --- a/docs/framework/angular/reference/type-aliases/DefinedInitialDataOptions.md +++ b/docs/framework/angular/reference/type-aliases/DefinedInitialDataOptions.md @@ -7,7 +7,10 @@ title: DefinedInitialDataOptions type DefinedInitialDataOptions = CreateQueryOptions & object; ``` -Defined in: [packages/angular-query/src/query-options.ts:39](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L39) +Defined in: [packages/angular-query/src/query-options.ts:79](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L79) + +The options accepted by the `queryOptions` overload selected when `initialData` is set — `data` is never +`undefined` (unless a `select` changes `TData` to include `undefined`). ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/DefinedQueryObserverResult.md b/docs/framework/angular/reference/type-aliases/DefinedQueryObserverResult.md index 7d3ecb06c3a..b8255e76028 100644 --- a/docs/framework/angular/reference/type-aliases/DefinedQueryObserverResult.md +++ b/docs/framework/angular/reference/type-aliases/DefinedQueryObserverResult.md @@ -9,7 +9,7 @@ type DefinedQueryObserverResult = | QueryObserverSuccessResult; ``` -Defined in: [packages/query-core/src/types.ts:1049](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1049) +Defined in: packages/query-core/dist-ts/src/types.d.ts:611 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/DistributiveOmit.md b/docs/framework/angular/reference/type-aliases/DistributiveOmit.md index 33b87a5cd6e..d710c6aaa83 100644 --- a/docs/framework/angular/reference/type-aliases/DistributiveOmit.md +++ b/docs/framework/angular/reference/type-aliases/DistributiveOmit.md @@ -7,7 +7,7 @@ title: DistributiveOmit type DistributiveOmit = TObject extends any ? Omit : never; ``` -Defined in: [packages/query-core/src/types.ts:14](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L14) +Defined in: packages/query-core/dist-ts/src/types.d.ts:10 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/EnsureInfiniteQueryDataOptions.md b/docs/framework/angular/reference/type-aliases/EnsureInfiniteQueryDataOptions.md index d824f1548bc..bd212056147 100644 --- a/docs/framework/angular/reference/type-aliases/EnsureInfiniteQueryDataOptions.md +++ b/docs/framework/angular/reference/type-aliases/EnsureInfiniteQueryDataOptions.md @@ -7,7 +7,7 @@ title: EnsureInfiniteQueryDataOptions type EnsureInfiniteQueryDataOptions = FetchInfiniteQueryOptions & object; ``` -Defined in: [packages/query-core/src/types.ts:690](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L690) +Defined in: packages/query-core/dist-ts/src/types.d.ts:345 ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/FetchInfiniteQueryOptions.md b/docs/framework/angular/reference/type-aliases/FetchInfiniteQueryOptions.md index 43c63fb4640..febf3f73368 100644 --- a/docs/framework/angular/reference/type-aliases/FetchInfiniteQueryOptions.md +++ b/docs/framework/angular/reference/type-aliases/FetchInfiniteQueryOptions.md @@ -7,7 +7,7 @@ title: FetchInfiniteQueryOptions type FetchInfiniteQueryOptions = Omit, TQueryKey, TPageParam>, "initialPageParam"> & InitialPageParam & InfiniteQueryPages; ``` -Defined in: [packages/query-core/src/types.ts:734](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L734) +Defined in: packages/query-core/dist-ts/src/types.d.ts:356 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/FetchStatus.md b/docs/framework/angular/reference/type-aliases/FetchStatus.md index ef8d40ec242..efcc41e7133 100644 --- a/docs/framework/angular/reference/type-aliases/FetchStatus.md +++ b/docs/framework/angular/reference/type-aliases/FetchStatus.md @@ -7,4 +7,4 @@ title: FetchStatus type FetchStatus = "fetching" | "paused" | "idle"; ``` -Defined in: [packages/query-core/src/types.ts:824](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L824) +Defined in: packages/query-core/dist-ts/src/types.d.ts:417 diff --git a/docs/framework/angular/reference/type-aliases/GetNextPageParamFunction.md b/docs/framework/angular/reference/type-aliases/GetNextPageParamFunction.md index c45a3d7ed14..61e538d5ab6 100644 --- a/docs/framework/angular/reference/type-aliases/GetNextPageParamFunction.md +++ b/docs/framework/angular/reference/type-aliases/GetNextPageParamFunction.md @@ -7,7 +7,7 @@ title: GetNextPageParamFunction type GetNextPageParamFunction = (lastPage: TQueryFnData, allPages: TQueryFnData[], lastPageParam: TPageParam, allPageParams: TPageParam[]) => TPageParam | undefined | null; ``` -Defined in: [packages/query-core/src/types.ts:240](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L240) +Defined in: packages/query-core/dist-ts/src/types.d.ts:76 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/GetPreviousPageParamFunction.md b/docs/framework/angular/reference/type-aliases/GetPreviousPageParamFunction.md index dd26d2e9c12..1729058e22e 100644 --- a/docs/framework/angular/reference/type-aliases/GetPreviousPageParamFunction.md +++ b/docs/framework/angular/reference/type-aliases/GetPreviousPageParamFunction.md @@ -7,7 +7,7 @@ title: GetPreviousPageParamFunction type GetPreviousPageParamFunction = (firstPage: TQueryFnData, allPages: TQueryFnData[], firstPageParam: TPageParam, allPageParams: TPageParam[]) => TPageParam | undefined | null; ``` -Defined in: [packages/query-core/src/types.ts:232](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L232) +Defined in: packages/query-core/dist-ts/src/types.d.ts:75 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/InferDataFromTag.md b/docs/framework/angular/reference/type-aliases/InferDataFromTag.md index 853bf7b1ec1..5002e47659c 100644 --- a/docs/framework/angular/reference/type-aliases/InferDataFromTag.md +++ b/docs/framework/angular/reference/type-aliases/InferDataFromTag.md @@ -7,7 +7,7 @@ title: InferDataFromTag type InferDataFromTag = TTaggedQueryKey extends DataTag ? TaggedValue : TQueryFnData; ``` -Defined in: [packages/query-core/src/types.ts:117](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L117) +Defined in: packages/query-core/dist-ts/src/types.d.ts:40 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/InferErrorFromTag.md b/docs/framework/angular/reference/type-aliases/InferErrorFromTag.md index 01a0a9e961f..d09b9c92ff3 100644 --- a/docs/framework/angular/reference/type-aliases/InferErrorFromTag.md +++ b/docs/framework/angular/reference/type-aliases/InferErrorFromTag.md @@ -7,7 +7,7 @@ title: InferErrorFromTag type InferErrorFromTag = TTaggedQueryKey extends DataTag ? TaggedError extends UnsetMarker ? TError : TaggedError : TError; ``` -Defined in: [packages/query-core/src/types.ts:122](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L122) +Defined in: packages/query-core/dist-ts/src/types.d.ts:41 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/InfiniteQueryExecuteOptions.md b/docs/framework/angular/reference/type-aliases/InfiniteQueryExecuteOptions.md index 411a5f73743..a2bbe2960a4 100644 --- a/docs/framework/angular/reference/type-aliases/InfiniteQueryExecuteOptions.md +++ b/docs/framework/angular/reference/type-aliases/InfiniteQueryExecuteOptions.md @@ -7,7 +7,7 @@ title: InfiniteQueryExecuteOptions type InfiniteQueryExecuteOptions = Omit, TQueryKey, TPageParam>, "initialPageParam"> & InitialPageParam & InfiniteQueryPages; ``` -Defined in: [packages/query-core/src/types.ts:713](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L713) +Defined in: packages/query-core/dist-ts/src/types.d.ts:354 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/InfiniteQueryObserverResult.md b/docs/framework/angular/reference/type-aliases/InfiniteQueryObserverResult.md index 6551ce57bde..eb252e5d1b6 100644 --- a/docs/framework/angular/reference/type-aliases/InfiniteQueryObserverResult.md +++ b/docs/framework/angular/reference/type-aliases/InfiniteQueryObserverResult.md @@ -12,7 +12,7 @@ type InfiniteQueryObserverResult = | InfiniteQueryObserverPlaceholderResult; ``` -Defined in: [packages/query-core/src/types.ts:1217](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1217) +Defined in: packages/query-core/dist-ts/src/types.d.ts:729 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/InitialDataFunction.md b/docs/framework/angular/reference/type-aliases/InitialDataFunction.md index 9c486b0e673..716025e656c 100644 --- a/docs/framework/angular/reference/type-aliases/InitialDataFunction.md +++ b/docs/framework/angular/reference/type-aliases/InitialDataFunction.md @@ -7,7 +7,7 @@ title: InitialDataFunction type InitialDataFunction = () => T | undefined; ``` -Defined in: [packages/query-core/src/types.ts:206](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L206) +Defined in: packages/query-core/dist-ts/src/types.d.ts:70 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/ManagedTimerId.md b/docs/framework/angular/reference/type-aliases/ManagedTimerId.md index d7833e3e4f0..48ac22cfbde 100644 --- a/docs/framework/angular/reference/type-aliases/ManagedTimerId.md +++ b/docs/framework/angular/reference/type-aliases/ManagedTimerId.md @@ -11,7 +11,7 @@ type ManagedTimerId = }; ``` -Defined in: [packages/query-core/src/timeoutManager.ts:17](https://github.com/TanStack/query/blob/main/packages/query-core/src/timeoutManager.ts#L17) +Defined in: packages/query-core/dist-ts/src/timeoutManager.d.ts:16 Wrapping `setTimeout` is awkward from a typing perspective because platform typings may extend the return type of `setTimeout`. For example, NodeJS diff --git a/docs/framework/angular/reference/type-aliases/MutateFunction.md b/docs/framework/angular/reference/type-aliases/MutateFunction.md index f0da2604213..b1aca3bb5f3 100644 --- a/docs/framework/angular/reference/type-aliases/MutateFunction.md +++ b/docs/framework/angular/reference/type-aliases/MutateFunction.md @@ -7,7 +7,7 @@ title: MutateFunction type MutateFunction = (...rest: MutateFunctionRest) => Promise; ``` -Defined in: [packages/query-core/src/types.ts:1446](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1446) +Defined in: packages/query-core/dist-ts/src/types.d.ts:811 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/MutateFunctionRest.md b/docs/framework/angular/reference/type-aliases/MutateFunctionRest.md index 4925164b8ad..f9f6c8609d6 100644 --- a/docs/framework/angular/reference/type-aliases/MutateFunctionRest.md +++ b/docs/framework/angular/reference/type-aliases/MutateFunctionRest.md @@ -7,7 +7,7 @@ title: MutateFunctionRest type MutateFunctionRest = undefined extends TVariables ? [TVariables, MutateOptions] : [TVariables, MutateOptions]; ``` -Defined in: [packages/query-core/src/types.ts:1431](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1431) +Defined in: packages/query-core/dist-ts/src/types.d.ts:804 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/MutationCacheNotifyEvent.md b/docs/framework/angular/reference/type-aliases/MutationCacheNotifyEvent.md index aa5e196bc72..ac7423a48e7 100644 --- a/docs/framework/angular/reference/type-aliases/MutationCacheNotifyEvent.md +++ b/docs/framework/angular/reference/type-aliases/MutationCacheNotifyEvent.md @@ -13,7 +13,7 @@ type MutationCacheNotifyEvent = | NotifyEventMutationUpdated; ``` -Defined in: [packages/query-core/src/mutationCache.ts:98](https://github.com/TanStack/query/blob/main/packages/query-core/src/mutationCache.ts#L98) +Defined in: packages/query-core/dist-ts/src/mutationCache.d.ts:59 The event passed to a `MutationCache` subscriber. Fired whenever a mutation is added or removed from the cache, its state is updated, or one of its observers is added, removed, or has its diff --git a/docs/framework/angular/reference/type-aliases/MutationFunction.md b/docs/framework/angular/reference/type-aliases/MutationFunction.md index d89b521daef..d23a11bc515 100644 --- a/docs/framework/angular/reference/type-aliases/MutationFunction.md +++ b/docs/framework/angular/reference/type-aliases/MutationFunction.md @@ -7,7 +7,7 @@ title: MutationFunction type MutationFunction = (variables: TVariables, context: MutationFunctionContext) => Promise; ``` -Defined in: [packages/query-core/src/types.ts:1272](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1272) +Defined in: packages/query-core/dist-ts/src/types.d.ts:745 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/MutationFunctionContext.md b/docs/framework/angular/reference/type-aliases/MutationFunctionContext.md index 971e8ac4e79..12cdb7ef43c 100644 --- a/docs/framework/angular/reference/type-aliases/MutationFunctionContext.md +++ b/docs/framework/angular/reference/type-aliases/MutationFunctionContext.md @@ -7,7 +7,7 @@ title: MutationFunctionContext type MutationFunctionContext = object; ``` -Defined in: [packages/query-core/src/types.ts:1265](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1265) +Defined in: packages/query-core/dist-ts/src/types.d.ts:740 ## Properties diff --git a/docs/framework/angular/reference/type-aliases/MutationKey.md b/docs/framework/angular/reference/type-aliases/MutationKey.md index 75918399443..71914c0dbe0 100644 --- a/docs/framework/angular/reference/type-aliases/MutationKey.md +++ b/docs/framework/angular/reference/type-aliases/MutationKey.md @@ -7,7 +7,4 @@ title: MutationKey type MutationKey = Register extends object ? TMutationKey extends ReadonlyArray ? TMutationKey : TMutationKey extends unknown[] ? TMutationKey : ReadonlyArray : ReadonlyArray; ``` -Defined in: [packages/query-core/src/types.ts:1231](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1231) - -The type of a mutation key — the serializable array used to identify and filter mutations. -Defaults to `ReadonlyArray`; declare `mutationKey` on [Register](../interfaces/Register.md) to narrow it repository-wide. +Defined in: packages/query-core/dist-ts/src/types.d.ts:730 diff --git a/docs/framework/angular/reference/type-aliases/MutationMeta.md b/docs/framework/angular/reference/type-aliases/MutationMeta.md index 1d4edc168f5..12d4316dcdb 100644 --- a/docs/framework/angular/reference/type-aliases/MutationMeta.md +++ b/docs/framework/angular/reference/type-aliases/MutationMeta.md @@ -7,7 +7,4 @@ title: MutationMeta type MutationMeta = Register extends object ? TMutationMeta extends Record ? TMutationMeta : Record : Record; ``` -Defined in: [packages/query-core/src/types.ts:1257](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1257) - -The type of the `meta` object that can be attached to a mutation and read back from `mutationFn`, callbacks and -cache-level handlers. Defaults to `Record`; declare `mutationMeta` on [Register](../interfaces/Register.md) to narrow it. +Defined in: packages/query-core/dist-ts/src/types.d.ts:737 diff --git a/docs/framework/angular/reference/type-aliases/MutationObserverResult.md b/docs/framework/angular/reference/type-aliases/MutationObserverResult.md index 62f5c66235e..2f82d1f2164 100644 --- a/docs/framework/angular/reference/type-aliases/MutationObserverResult.md +++ b/docs/framework/angular/reference/type-aliases/MutationObserverResult.md @@ -11,7 +11,7 @@ type MutationObserverResult = | MutationObserverSuccessResult; ``` -Defined in: [packages/query-core/src/types.ts:1604](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1604) +Defined in: packages/query-core/dist-ts/src/types.d.ts:911 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/MutationScope.md b/docs/framework/angular/reference/type-aliases/MutationScope.md index 01d65461e85..8484ccd20b8 100644 --- a/docs/framework/angular/reference/type-aliases/MutationScope.md +++ b/docs/framework/angular/reference/type-aliases/MutationScope.md @@ -7,11 +7,7 @@ title: MutationScope type MutationScope = object; ``` -Defined in: [packages/query-core/src/types.ts:1249](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1249) - -Groups mutations so they run one after another instead of in parallel. -Mutations that share the same `id` form a queue: while one is running, the others wait in `isPaused: true` -state and resume automatically when their turn comes. Mutations with no scope always run in parallel. +Defined in: packages/query-core/dist-ts/src/types.d.ts:734 ## Properties diff --git a/docs/framework/angular/reference/type-aliases/MutationStateOptions.md b/docs/framework/angular/reference/type-aliases/MutationStateOptions.md index dfd8018782b..dd42b35eb82 100644 --- a/docs/framework/angular/reference/type-aliases/MutationStateOptions.md +++ b/docs/framework/angular/reference/type-aliases/MutationStateOptions.md @@ -13,38 +13,15 @@ Defined in: [packages/angular-query/src/inject-mutation-state.ts:23](https://git ### TResult -`TResult` = `MutationState` +`TResult` = [`MutationState`](../interfaces/MutationState.md) ### TMutation -`TMutation` *extends* `Mutation`\<`any`, `any`, `any`, `any`\> = `MutationTypeFromResult`\<`TResult`\> +`TMutation` *extends* [`Mutation`](../classes/Mutation.md)\<`any`, `any`, `any`, `any`\> = `MutationTypeFromResult`\<`TResult`\> ## Properties -### filters? - -```ts -optional filters: MutationFilters; -``` - -Defined in: [packages/angular-query/src/inject-mutation-state.ts:28](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-mutation-state.ts#L28) - -*** - -### select()? - -```ts -optional select: (mutation) => TResult; -``` - -Defined in: [packages/angular-query/src/inject-mutation-state.ts:29](https://github.com/TanStack/query/blob/main/packages/angular-query/src/inject-mutation-state.ts#L29) - -#### Parameters - -##### mutation - -`TMutation` - -#### Returns - -`TResult` +| Property | Type | +| ------ | ------ | +| `filters?` | [`MutationFilters`](../interfaces/MutationFilters.md) | +| `select?` | (`mutation`: `TMutation`) => `TResult` | diff --git a/docs/framework/angular/reference/type-aliases/MutationStatus.md b/docs/framework/angular/reference/type-aliases/MutationStatus.md index d992166bf5e..5e5b1d7a0f4 100644 --- a/docs/framework/angular/reference/type-aliases/MutationStatus.md +++ b/docs/framework/angular/reference/type-aliases/MutationStatus.md @@ -7,4 +7,4 @@ title: MutationStatus type MutationStatus = "idle" | "pending" | "success" | "error"; ``` -Defined in: [packages/query-core/src/types.ts:1242](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1242) +Defined in: packages/query-core/dist-ts/src/types.d.ts:733 diff --git a/docs/framework/angular/reference/type-aliases/NetworkMode.md b/docs/framework/angular/reference/type-aliases/NetworkMode.md index a727cb06530..bf1d4beb5b2 100644 --- a/docs/framework/angular/reference/type-aliases/NetworkMode.md +++ b/docs/framework/angular/reference/type-aliases/NetworkMode.md @@ -7,4 +7,4 @@ title: NetworkMode type NetworkMode = "online" | "always" | "offlineFirst"; ``` -Defined in: [packages/query-core/src/types.ts:269](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L269) +Defined in: packages/query-core/dist-ts/src/types.d.ts:84 diff --git a/docs/framework/angular/reference/type-aliases/NonUndefinedGuard.md b/docs/framework/angular/reference/type-aliases/NonUndefinedGuard.md index 4aaf208013b..2b3d791fe6b 100644 --- a/docs/framework/angular/reference/type-aliases/NonUndefinedGuard.md +++ b/docs/framework/angular/reference/type-aliases/NonUndefinedGuard.md @@ -7,7 +7,7 @@ title: NonUndefinedGuard type NonUndefinedGuard = T extends undefined ? never : T; ``` -Defined in: [packages/query-core/src/types.ts:12](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L12) +Defined in: packages/query-core/dist-ts/src/types.d.ts:9 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/NotifyEventType.md b/docs/framework/angular/reference/type-aliases/NotifyEventType.md index f9fcac2cbf1..b216a1cd167 100644 --- a/docs/framework/angular/reference/type-aliases/NotifyEventType.md +++ b/docs/framework/angular/reference/type-aliases/NotifyEventType.md @@ -14,4 +14,4 @@ type NotifyEventType = | "observerOptionsUpdated"; ``` -Defined in: [packages/query-core/src/types.ts:1660](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1660) +Defined in: packages/query-core/dist-ts/src/types.d.ts:940 diff --git a/docs/framework/angular/reference/type-aliases/NotifyOnChangeProps.md b/docs/framework/angular/reference/type-aliases/NotifyOnChangeProps.md index 9cd620e79d1..df9661cae57 100644 --- a/docs/framework/angular/reference/type-aliases/NotifyOnChangeProps.md +++ b/docs/framework/angular/reference/type-aliases/NotifyOnChangeProps.md @@ -14,4 +14,4 @@ type NotifyOnChangeProps = | undefined; ``` -Defined in: [packages/query-core/src/types.ts:272](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L272) +Defined in: packages/query-core/dist-ts/src/types.d.ts:85 diff --git a/docs/framework/angular/reference/type-aliases/OmitKeyof.md b/docs/framework/angular/reference/type-aliases/OmitKeyof.md index 690a7b0a5d2..111b9a8793e 100644 --- a/docs/framework/angular/reference/type-aliases/OmitKeyof.md +++ b/docs/framework/angular/reference/type-aliases/OmitKeyof.md @@ -7,7 +7,7 @@ title: OmitKeyof type OmitKeyof = Omit; ``` -Defined in: [packages/query-core/src/types.ts:19](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L19) +Defined in: packages/query-core/dist-ts/src/types.d.ts:11 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/Override.md b/docs/framework/angular/reference/type-aliases/Override.md index 8abcecd1e1b..ae9348d04df 100644 --- a/docs/framework/angular/reference/type-aliases/Override.md +++ b/docs/framework/angular/reference/type-aliases/Override.md @@ -7,7 +7,7 @@ title: Override type Override = { [AKey in keyof TTargetA]: AKey extends keyof TTargetB ? TTargetB[AKey] : TTargetA[AKey] }; ``` -Defined in: [packages/query-core/src/types.ts:31](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L31) +Defined in: packages/query-core/dist-ts/src/types.d.ts:12 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/PlaceholderDataFunction.md b/docs/framework/angular/reference/type-aliases/PlaceholderDataFunction.md index 456b9e6a646..4e44863403a 100644 --- a/docs/framework/angular/reference/type-aliases/PlaceholderDataFunction.md +++ b/docs/framework/angular/reference/type-aliases/PlaceholderDataFunction.md @@ -9,7 +9,7 @@ type PlaceholderDataFunction = (pre | undefined) => TQueryData | undefined; ``` -Defined in: [packages/query-core/src/types.ts:211](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L211) +Defined in: packages/query-core/dist-ts/src/types.d.ts:72 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/QueriesOptions.md b/docs/framework/angular/reference/type-aliases/QueriesOptions.md index 411f34c036f..4f52e650484 100644 --- a/docs/framework/angular/reference/type-aliases/QueriesOptions.md +++ b/docs/framework/angular/reference/type-aliases/QueriesOptions.md @@ -15,18 +15,10 @@ Defined in: [packages/angular-query/src/inject-queries.types.ts:141](https://git `T` *extends* `any`[] -The type of the `queries` array as written at the call site. - ### TResults `TResults` *extends* `any`[] = \[\] -The internal accumulator that this type builds during recursion. It is not meant to -be set explicitly. - ### TDepth `TDepth` *extends* `ReadonlyArray`\<`number`\> = \[\] - -The internal recursion-depth counter, checked against the 20-element limit. It is not -meant to be set explicitly. diff --git a/docs/framework/angular/reference/type-aliases/QueriesPlaceholderDataFunction.md b/docs/framework/angular/reference/type-aliases/QueriesPlaceholderDataFunction.md index 91b17786504..eb681438a86 100644 --- a/docs/framework/angular/reference/type-aliases/QueriesPlaceholderDataFunction.md +++ b/docs/framework/angular/reference/type-aliases/QueriesPlaceholderDataFunction.md @@ -7,7 +7,7 @@ title: QueriesPlaceholderDataFunction type QueriesPlaceholderDataFunction = (previousData: undefined, previousQuery: undefined) => TQueryData | undefined; ``` -Defined in: [packages/query-core/src/types.ts:221](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L221) +Defined in: packages/query-core/dist-ts/src/types.d.ts:73 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/QueriesResults.md b/docs/framework/angular/reference/type-aliases/QueriesResults.md index 8bf2b78c875..444e20641eb 100644 --- a/docs/framework/angular/reference/type-aliases/QueriesResults.md +++ b/docs/framework/angular/reference/type-aliases/QueriesResults.md @@ -15,18 +15,10 @@ Defined in: [packages/angular-query/src/inject-queries.types.ts:177](https://git `T` *extends* `any`[] -The type of the `queries` array, as inferred by [QueriesOptions](QueriesOptions.md). - ### TResults `TResults` *extends* `any`[] = \[\] -The internal accumulator that this type builds during recursion. It is not meant to -be set explicitly. - ### TDepth `TDepth` *extends* `ReadonlyArray`\<`number`\> = \[\] - -The internal recursion-depth counter, checked against the 20-element limit. It is not -meant to be set explicitly. diff --git a/docs/framework/angular/reference/type-aliases/QueryBooleanOption.md b/docs/framework/angular/reference/type-aliases/QueryBooleanOption.md index c992ec0c638..8331b26a899 100644 --- a/docs/framework/angular/reference/type-aliases/QueryBooleanOption.md +++ b/docs/framework/angular/reference/type-aliases/QueryBooleanOption.md @@ -9,7 +9,7 @@ type QueryBooleanOption = | (query: Query) => boolean; ``` -Defined in: [packages/query-core/src/types.ts:150](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L150) +Defined in: packages/query-core/dist-ts/src/types.d.ts:45 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/QueryCacheNotifyEvent.md b/docs/framework/angular/reference/type-aliases/QueryCacheNotifyEvent.md index b92c76fb826..d6485450a3d 100644 --- a/docs/framework/angular/reference/type-aliases/QueryCacheNotifyEvent.md +++ b/docs/framework/angular/reference/type-aliases/QueryCacheNotifyEvent.md @@ -14,7 +14,7 @@ type QueryCacheNotifyEvent = | NotifyEventQueryObserverOptionsUpdated; ``` -Defined in: [packages/query-core/src/queryCache.ts:85](https://github.com/TanStack/query/blob/main/packages/query-core/src/queryCache.ts#L85) +Defined in: packages/query-core/dist-ts/src/queryCache.d.ts:59 The event passed to a `QueryCache` subscriber. Fired whenever a query is added or removed from the cache, its state is updated (e.g. via `query.setState` or `queryClient.removeQueries`), or diff --git a/docs/framework/angular/reference/type-aliases/QueryFunction.md b/docs/framework/angular/reference/type-aliases/QueryFunction.md index e1682277f1b..a01ebe2aa8c 100644 --- a/docs/framework/angular/reference/type-aliases/QueryFunction.md +++ b/docs/framework/angular/reference/type-aliases/QueryFunction.md @@ -7,7 +7,7 @@ title: QueryFunction type QueryFunction = (context: QueryFunctionContext) => T | Promise; ``` -Defined in: [packages/query-core/src/types.ts:130](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L130) +Defined in: packages/query-core/dist-ts/src/types.d.ts:42 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/QueryFunctionContext.md b/docs/framework/angular/reference/type-aliases/QueryFunctionContext.md index 6ea82d0aeef..827204a9f79 100644 --- a/docs/framework/angular/reference/type-aliases/QueryFunctionContext.md +++ b/docs/framework/angular/reference/type-aliases/QueryFunctionContext.md @@ -7,7 +7,7 @@ title: QueryFunctionContext type QueryFunctionContext = [TPageParam] extends [never] ? object : object; ``` -Defined in: [packages/query-core/src/types.ts:176](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L176) +Defined in: packages/query-core/dist-ts/src/types.d.ts:47 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/QueryKey.md b/docs/framework/angular/reference/type-aliases/QueryKey.md index 51447f90fb7..029efdb5756 100644 --- a/docs/framework/angular/reference/type-aliases/QueryKey.md +++ b/docs/framework/angular/reference/type-aliases/QueryKey.md @@ -7,7 +7,4 @@ title: QueryKey type QueryKey = Register extends object ? TQueryKey extends ReadonlyArray ? TQueryKey : TQueryKey extends unknown[] ? TQueryKey : ReadonlyArray : ReadonlyArray; ``` -Defined in: [packages/query-core/src/types.ts:78](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L78) - -The type of a query key — the serializable array that identifies a query in the cache. -Defaults to `ReadonlyArray`; declare `queryKey` on [Register](../interfaces/Register.md) to narrow it repository-wide. +Defined in: packages/query-core/dist-ts/src/types.d.ts:20 diff --git a/docs/framework/angular/reference/type-aliases/QueryKeyHashFunction.md b/docs/framework/angular/reference/type-aliases/QueryKeyHashFunction.md index 6f77c8928b8..364a1e4d3bb 100644 --- a/docs/framework/angular/reference/type-aliases/QueryKeyHashFunction.md +++ b/docs/framework/angular/reference/type-aliases/QueryKeyHashFunction.md @@ -7,7 +7,7 @@ title: QueryKeyHashFunction type QueryKeyHashFunction = (queryKey: TQueryKey) => string; ``` -Defined in: [packages/query-core/src/types.ts:227](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L227) +Defined in: packages/query-core/dist-ts/src/types.d.ts:74 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/QueryKeyWithDataTag.md b/docs/framework/angular/reference/type-aliases/QueryKeyWithDataTag.md index 02b78b28803..41fa048599e 100644 --- a/docs/framework/angular/reference/type-aliases/QueryKeyWithDataTag.md +++ b/docs/framework/angular/reference/type-aliases/QueryKeyWithDataTag.md @@ -7,7 +7,7 @@ title: QueryKeyWithDataTag type QueryKeyWithDataTag = object; ``` -Defined in: [packages/query-core/src/types.ts:109](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L109) +Defined in: packages/query-core/dist-ts/src/types.d.ts:37 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/QueryMeta.md b/docs/framework/angular/reference/type-aliases/QueryMeta.md index 25a245699b2..bc344eb6a6b 100644 --- a/docs/framework/angular/reference/type-aliases/QueryMeta.md +++ b/docs/framework/angular/reference/type-aliases/QueryMeta.md @@ -7,7 +7,4 @@ title: QueryMeta type QueryMeta = Register extends object ? TQueryMeta extends Record ? TQueryMeta : Record : Record; ``` -Defined in: [packages/query-core/src/types.ts:260](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L260) - -The type of the `meta` object that can be attached to a query and read back from `queryFn`, callbacks and -cache-level handlers. Defaults to `Record`; declare `queryMeta` on [Register](../interfaces/Register.md) to narrow it. +Defined in: packages/query-core/dist-ts/src/types.d.ts:81 diff --git a/docs/framework/angular/reference/type-aliases/QueryObserverResult.md b/docs/framework/angular/reference/type-aliases/QueryObserverResult.md index a4cfc23b2dc..28a7824a72c 100644 --- a/docs/framework/angular/reference/type-aliases/QueryObserverResult.md +++ b/docs/framework/angular/reference/type-aliases/QueryObserverResult.md @@ -12,7 +12,7 @@ type QueryObserverResult = | QueryObserverPlaceholderResult; ``` -Defined in: [packages/query-core/src/types.ts:1056](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1056) +Defined in: packages/query-core/dist-ts/src/types.d.ts:612 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/QueryPersister.md b/docs/framework/angular/reference/type-aliases/QueryPersister.md index 8eedf698a9c..03cb812c32f 100644 --- a/docs/framework/angular/reference/type-aliases/QueryPersister.md +++ b/docs/framework/angular/reference/type-aliases/QueryPersister.md @@ -7,7 +7,7 @@ title: QueryPersister type QueryPersister = [TPageParam] extends [never] ? (queryFn: QueryFunction, context: QueryFunctionContext, query: Query) => T | Promise : (queryFn: QueryFunction, context: QueryFunctionContext, query: Query) => T | Promise; ``` -Defined in: [packages/query-core/src/types.ts:160](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L160) +Defined in: packages/query-core/dist-ts/src/types.d.ts:46 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/QueryStatus.md b/docs/framework/angular/reference/type-aliases/QueryStatus.md index d05efb93202..e88a59c22d5 100644 --- a/docs/framework/angular/reference/type-aliases/QueryStatus.md +++ b/docs/framework/angular/reference/type-aliases/QueryStatus.md @@ -7,4 +7,4 @@ title: QueryStatus type QueryStatus = "pending" | "error" | "success"; ``` -Defined in: [packages/query-core/src/types.ts:822](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L822) +Defined in: packages/query-core/dist-ts/src/types.d.ts:416 diff --git a/docs/framework/angular/reference/type-aliases/SkipToken.md b/docs/framework/angular/reference/type-aliases/SkipToken.md index 680ea705e5e..9f05ee57ab2 100644 --- a/docs/framework/angular/reference/type-aliases/SkipToken.md +++ b/docs/framework/angular/reference/type-aliases/SkipToken.md @@ -7,6 +7,6 @@ title: SkipToken type SkipToken = typeof skipToken; ``` -Defined in: [packages/query-core/src/utils.ts:532](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L532) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:186 The type of the [skipToken](../variables/skipToken.md) sentinel value. diff --git a/docs/framework/angular/reference/type-aliases/StaleTime.md b/docs/framework/angular/reference/type-aliases/StaleTime.md index a16040761e6..c67335d2b64 100644 --- a/docs/framework/angular/reference/type-aliases/StaleTime.md +++ b/docs/framework/angular/reference/type-aliases/StaleTime.md @@ -7,4 +7,4 @@ title: StaleTime type StaleTime = number | "static"; ``` -Defined in: [packages/query-core/src/types.ts:137](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L137) +Defined in: packages/query-core/dist-ts/src/types.d.ts:43 diff --git a/docs/framework/angular/reference/type-aliases/StaleTimeFunction.md b/docs/framework/angular/reference/type-aliases/StaleTimeFunction.md index ec4e9f7b98d..0e276c7f0b7 100644 --- a/docs/framework/angular/reference/type-aliases/StaleTimeFunction.md +++ b/docs/framework/angular/reference/type-aliases/StaleTimeFunction.md @@ -5,11 +5,11 @@ title: StaleTimeFunction ```ts type StaleTimeFunction = - | number | "static" - | (query: Query) => number | "static"; + | StaleTime + | (query: Query) => StaleTime; ``` -Defined in: [packages/query-core/src/types.ts:140](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L140) +Defined in: packages/query-core/dist-ts/src/types.d.ts:44 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/ThrowOnError.md b/docs/framework/angular/reference/type-aliases/ThrowOnError.md index b4a3916b8cf..ed5ba494fee 100644 --- a/docs/framework/angular/reference/type-aliases/ThrowOnError.md +++ b/docs/framework/angular/reference/type-aliases/ThrowOnError.md @@ -9,7 +9,7 @@ type ThrowOnError = | (error: TError, query: Query) => boolean; ``` -Defined in: [packages/query-core/src/types.ts:423](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L423) +Defined in: packages/query-core/dist-ts/src/types.d.ts:209 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/TimeoutCallback.md b/docs/framework/angular/reference/type-aliases/TimeoutCallback.md index e2a9b2a2161..be617450ba9 100644 --- a/docs/framework/angular/reference/type-aliases/TimeoutCallback.md +++ b/docs/framework/angular/reference/type-aliases/TimeoutCallback.md @@ -7,7 +7,7 @@ title: TimeoutCallback type TimeoutCallback = (_: void) => void; ``` -Defined in: [packages/query-core/src/timeoutManager.ts:9](https://github.com/TanStack/query/blob/main/packages/query-core/src/timeoutManager.ts#L9) +Defined in: packages/query-core/dist-ts/src/timeoutManager.d.ts:9 [TimeoutManager](../interfaces/TimeoutManager.md) does not support passing arguments to the callback. diff --git a/docs/framework/angular/reference/type-aliases/TimeoutProvider.md b/docs/framework/angular/reference/type-aliases/TimeoutProvider.md index e74ad3a36d5..8505660ee05 100644 --- a/docs/framework/angular/reference/type-aliases/TimeoutProvider.md +++ b/docs/framework/angular/reference/type-aliases/TimeoutProvider.md @@ -7,7 +7,7 @@ title: TimeoutProvider type TimeoutProvider = object; ``` -Defined in: [packages/query-core/src/timeoutManager.ts:28](https://github.com/TanStack/query/blob/main/packages/query-core/src/timeoutManager.ts#L28) +Defined in: packages/query-core/dist-ts/src/timeoutManager.d.ts:28 Backend for timer functions. diff --git a/docs/framework/angular/reference/type-aliases/UndefinedInitialDataInfiniteOptions.md b/docs/framework/angular/reference/type-aliases/UndefinedInitialDataInfiniteOptions.md index 50e5e3feaa7..435f0959c3d 100644 --- a/docs/framework/angular/reference/type-aliases/UndefinedInitialDataInfiniteOptions.md +++ b/docs/framework/angular/reference/type-aliases/UndefinedInitialDataInfiniteOptions.md @@ -7,7 +7,10 @@ title: UndefinedInitialDataInfiniteOptions type UndefinedInitialDataInfiniteOptions = CreateInfiniteQueryOptions & object; ``` -Defined in: [packages/angular-query/src/infinite-query-options.ts:13](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L13) +Defined in: [packages/angular-query/src/infinite-query-options.ts:24](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L24) + +The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set — `data` +may be `undefined` while the query is `pending`. ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/UndefinedInitialDataOptions.md b/docs/framework/angular/reference/type-aliases/UndefinedInitialDataOptions.md index 54d2db71cb2..ad6607e2132 100644 --- a/docs/framework/angular/reference/type-aliases/UndefinedInitialDataOptions.md +++ b/docs/framework/angular/reference/type-aliases/UndefinedInitialDataOptions.md @@ -7,7 +7,10 @@ title: UndefinedInitialDataOptions type UndefinedInitialDataOptions = CreateQueryOptions & object; ``` -Defined in: [packages/angular-query/src/query-options.ts:12](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L12) +Defined in: [packages/angular-query/src/query-options.ts:21](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L21) + +The options accepted by the `queryOptions` overload selected when no `initialData` is set — `data` may be +`undefined` while the query is `pending`. ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/UnsetMarker.md b/docs/framework/angular/reference/type-aliases/UnsetMarker.md index 83356a74e58..43e02873465 100644 --- a/docs/framework/angular/reference/type-aliases/UnsetMarker.md +++ b/docs/framework/angular/reference/type-aliases/UnsetMarker.md @@ -7,4 +7,4 @@ title: UnsetMarker type UnsetMarker = typeof unsetMarker; ``` -Defined in: [packages/query-core/src/types.ts:93](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L93) +Defined in: packages/query-core/dist-ts/src/types.d.ts:28 diff --git a/docs/framework/angular/reference/type-aliases/UnusedSkipTokenInfiniteOptions.md b/docs/framework/angular/reference/type-aliases/UnusedSkipTokenInfiniteOptions.md index 70c4640c4c1..1e97bfb29c3 100644 --- a/docs/framework/angular/reference/type-aliases/UnusedSkipTokenInfiniteOptions.md +++ b/docs/framework/angular/reference/type-aliases/UnusedSkipTokenInfiniteOptions.md @@ -7,7 +7,11 @@ title: UnusedSkipTokenInfiniteOptions type UnusedSkipTokenInfiniteOptions = OmitKeyof, "queryFn"> & object; ``` -Defined in: [packages/angular-query/src/infinite-query-options.ts:34](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L34) +Defined in: [packages/angular-query/src/infinite-query-options.ts:64](https://github.com/TanStack/query/blob/main/packages/angular-query/src/infinite-query-options.ts#L64) + +The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set and +`queryFn` is not `skipToken` — same as [UndefinedInitialDataInfiniteOptions](UndefinedInitialDataInfiniteOptions.md), but `queryFn` may not be +`skipToken`. ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/UnusedSkipTokenOptions.md b/docs/framework/angular/reference/type-aliases/UnusedSkipTokenOptions.md index 65c192aee95..865a07b8eba 100644 --- a/docs/framework/angular/reference/type-aliases/UnusedSkipTokenOptions.md +++ b/docs/framework/angular/reference/type-aliases/UnusedSkipTokenOptions.md @@ -7,7 +7,10 @@ title: UnusedSkipTokenOptions type UnusedSkipTokenOptions = OmitKeyof, "queryFn"> & object; ``` -Defined in: [packages/angular-query/src/query-options.ts:24](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L24) +Defined in: [packages/angular-query/src/query-options.ts:49](https://github.com/TanStack/query/blob/main/packages/angular-query/src/query-options.ts#L49) + +The options accepted by the `queryOptions` overload selected when no `initialData` is set and `queryFn` is +not `skipToken` — same as [UndefinedInitialDataOptions](UndefinedInitialDataOptions.md), but `queryFn` may not be `skipToken`. ## Type Declaration diff --git a/docs/framework/angular/reference/type-aliases/Updater.md b/docs/framework/angular/reference/type-aliases/Updater.md index 86d38355a0b..c1098cc1cda 100644 --- a/docs/framework/angular/reference/type-aliases/Updater.md +++ b/docs/framework/angular/reference/type-aliases/Updater.md @@ -7,7 +7,7 @@ title: Updater type Updater = TOutput | (input: TInput) => TOutput; ``` -Defined in: [packages/query-core/src/utils.ts:105](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L105) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:78 Either a plain value of type `TOutput`, or a function that receives `TInput` and returns `TOutput`. Used for example by `setQueryData`-style updaters, which accept either the new data directly or a diff --git a/docs/framework/angular/reference/type-aliases/WithRequired.md b/docs/framework/angular/reference/type-aliases/WithRequired.md index a12a324a983..07fd20af83a 100644 --- a/docs/framework/angular/reference/type-aliases/WithRequired.md +++ b/docs/framework/angular/reference/type-aliases/WithRequired.md @@ -7,7 +7,7 @@ title: WithRequired type WithRequired = TTarget & { [_ in TKey]: {} }; ``` -Defined in: [packages/query-core/src/types.ts:579](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L579) +Defined in: packages/query-core/dist-ts/src/types.d.ts:315 ## Type Parameters diff --git a/docs/framework/angular/reference/type-aliases/dataTagErrorSymbol.md b/docs/framework/angular/reference/type-aliases/dataTagErrorSymbol.md index 03cc2c00ee6..c1c29257408 100644 --- a/docs/framework/angular/reference/type-aliases/dataTagErrorSymbol.md +++ b/docs/framework/angular/reference/type-aliases/dataTagErrorSymbol.md @@ -7,4 +7,4 @@ title: dataTagErrorSymbol type dataTagErrorSymbol = typeof dataTagErrorSymbol; ``` -Defined in: [packages/query-core/src/types.ts:90](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L90) +Defined in: packages/query-core/dist-ts/src/types.d.ts:25 diff --git a/docs/framework/angular/reference/type-aliases/dataTagSymbol.md b/docs/framework/angular/reference/type-aliases/dataTagSymbol.md index f2228d88a35..0935b5bd1a6 100644 --- a/docs/framework/angular/reference/type-aliases/dataTagSymbol.md +++ b/docs/framework/angular/reference/type-aliases/dataTagSymbol.md @@ -7,4 +7,4 @@ title: dataTagSymbol type dataTagSymbol = typeof dataTagSymbol; ``` -Defined in: [packages/query-core/src/types.ts:88](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L88) +Defined in: packages/query-core/dist-ts/src/types.d.ts:23 diff --git a/docs/framework/angular/reference/variables/dataTagErrorSymbol.md b/docs/framework/angular/reference/variables/dataTagErrorSymbol.md index 90d0e92ca93..73f8a605c98 100644 --- a/docs/framework/angular/reference/variables/dataTagErrorSymbol.md +++ b/docs/framework/angular/reference/variables/dataTagErrorSymbol.md @@ -4,7 +4,7 @@ title: dataTagErrorSymbol --- ```ts -const dataTagErrorSymbol: typeof dataTagErrorSymbol; +const dataTagErrorSymbol: unique symbol; ``` -Defined in: [packages/query-core/src/types.ts:90](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L90) +Defined in: packages/query-core/dist-ts/src/types.d.ts:25 diff --git a/docs/framework/angular/reference/variables/dataTagSymbol.md b/docs/framework/angular/reference/variables/dataTagSymbol.md index 0eb15cc3bc8..14cbc63ec9b 100644 --- a/docs/framework/angular/reference/variables/dataTagSymbol.md +++ b/docs/framework/angular/reference/variables/dataTagSymbol.md @@ -4,7 +4,7 @@ title: dataTagSymbol --- ```ts -const dataTagSymbol: typeof dataTagSymbol; +const dataTagSymbol: unique symbol; ``` -Defined in: [packages/query-core/src/types.ts:88](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L88) +Defined in: packages/query-core/dist-ts/src/types.d.ts:23 diff --git a/docs/framework/angular/reference/variables/defaultScheduler.md b/docs/framework/angular/reference/variables/defaultScheduler.md index 70e14d3f846..260ac9572c2 100644 --- a/docs/framework/angular/reference/variables/defaultScheduler.md +++ b/docs/framework/angular/reference/variables/defaultScheduler.md @@ -4,10 +4,10 @@ title: defaultScheduler --- ```ts -const defaultScheduler: ScheduleFunction = systemSetTimeoutZero; +const defaultScheduler: ScheduleFunction; ``` -Defined in: [packages/query-core/src/notifyManager.ts:19](https://github.com/TanStack/query/blob/main/packages/query-core/src/notifyManager.ts#L19) +Defined in: packages/query-core/dist-ts/src/notifyManager.d.ts:10 Default scheduling function used by the notify manager. Schedules the callback with the system's `setTimeout(callback, 0)`. diff --git a/docs/framework/angular/reference/variables/environmentManager.md b/docs/framework/angular/reference/variables/environmentManager.md index 4f88d27d2a9..1d1825bdc6b 100644 --- a/docs/framework/angular/reference/variables/environmentManager.md +++ b/docs/framework/angular/reference/variables/environmentManager.md @@ -7,7 +7,7 @@ title: environmentManager const environmentManager: object; ``` -Defined in: [packages/query-core/src/environmentManager.ts:29](https://github.com/TanStack/query/blob/main/packages/query-core/src/environmentManager.ts#L29) +Defined in: packages/query-core/dist-ts/src/environmentManager.d.ts:23 Manages how TanStack Query detects whether the current runtime should be treated as server-side, which disables scheduling refetch timers and changes the default `retry` count @@ -26,8 +26,6 @@ behave like a client. isServer: () => boolean; ``` -Returns whether the current runtime should be treated as a server environment. - #### Returns `boolean` diff --git a/docs/framework/angular/reference/variables/focusManager.md b/docs/framework/angular/reference/variables/focusManager.md index 86477849e06..88f85eea879 100644 --- a/docs/framework/angular/reference/variables/focusManager.md +++ b/docs/framework/angular/reference/variables/focusManager.md @@ -7,6 +7,6 @@ title: focusManager const focusManager: FocusManager; ``` -Defined in: [packages/query-core/src/focusManager.ts:142](https://github.com/TanStack/query/blob/main/packages/query-core/src/focusManager.ts#L142) +Defined in: packages/query-core/dist-ts/src/focusManager.d.ts:71 Singleton instance of [FocusManager](../interfaces/FocusManager.md), used to manage and observe the focus state within TanStack Query. diff --git a/docs/framework/angular/reference/variables/isServer.md b/docs/framework/angular/reference/variables/isServer.md index 16aa39d1244..a2ea7a5c82a 100644 --- a/docs/framework/angular/reference/variables/isServer.md +++ b/docs/framework/angular/reference/variables/isServer.md @@ -7,7 +7,7 @@ title: isServer const isServer: boolean; ``` -Defined in: [packages/query-core/src/utils.ts:114](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L114) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:83 ## Deprecated diff --git a/docs/framework/angular/reference/variables/notifyManager.md b/docs/framework/angular/reference/variables/notifyManager.md index c2c071b42a5..51d99f10059 100644 --- a/docs/framework/angular/reference/variables/notifyManager.md +++ b/docs/framework/angular/reference/variables/notifyManager.md @@ -7,7 +7,7 @@ title: notifyManager const notifyManager: object; ``` -Defined in: [packages/query-core/src/notifyManager.ts:144](https://github.com/TanStack/query/blob/main/packages/query-core/src/notifyManager.ts#L144) +Defined in: packages/query-core/dist-ts/src/notifyManager.d.ts:70 Handles scheduling and batching callbacks in TanStack Query. @@ -67,7 +67,7 @@ All calls to the wrapped function will be batched. ### schedule() ```ts -schedule: (callback: NotifyCallback) => void; +readonly schedule: (callback: NotifyCallback) => void; ``` Schedules a function to be run on the next batch. diff --git a/docs/framework/angular/reference/variables/onlineManager.md b/docs/framework/angular/reference/variables/onlineManager.md index 2eeec5385d8..c62e2a55362 100644 --- a/docs/framework/angular/reference/variables/onlineManager.md +++ b/docs/framework/angular/reference/variables/onlineManager.md @@ -7,6 +7,6 @@ title: onlineManager const onlineManager: OnlineManager; ``` -Defined in: [packages/query-core/src/onlineManager.ts:117](https://github.com/TanStack/query/blob/main/packages/query-core/src/onlineManager.ts#L117) +Defined in: packages/query-core/dist-ts/src/onlineManager.d.ts:60 Singleton instance of [OnlineManager](../interfaces/OnlineManager.md), used to manage and observe the online state within TanStack Query. diff --git a/docs/framework/angular/reference/variables/skipToken.md b/docs/framework/angular/reference/variables/skipToken.md index 820b2cc8938..fd5aece6e33 100644 --- a/docs/framework/angular/reference/variables/skipToken.md +++ b/docs/framework/angular/reference/variables/skipToken.md @@ -4,10 +4,10 @@ title: skipToken --- ```ts -const skipToken: typeof skipToken; +const skipToken: unique symbol; ``` -Defined in: [packages/query-core/src/utils.ts:528](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L528) +Defined in: packages/query-core/dist-ts/src/utils.d.ts:182 Sentinel value that can be passed as a query's `queryFn` to conditionally disable the query (equivalent to `enabled: false`) while preserving full type inference for the query's data. Unlike `enabled: false`, diff --git a/docs/framework/angular/reference/variables/timeoutManager.md b/docs/framework/angular/reference/variables/timeoutManager.md index 1eca1a5f343..f99ede3311a 100644 --- a/docs/framework/angular/reference/variables/timeoutManager.md +++ b/docs/framework/angular/reference/variables/timeoutManager.md @@ -7,6 +7,6 @@ title: timeoutManager const timeoutManager: TimeoutManager; ``` -Defined in: [packages/query-core/src/timeoutManager.ts:232](https://github.com/TanStack/query/blob/main/packages/query-core/src/timeoutManager.ts#L232) +Defined in: packages/query-core/dist-ts/src/timeoutManager.d.ts:153 Singleton instance of [TimeoutManager](../interfaces/TimeoutManager.md), used throughout TanStack Query to schedule and cancel timers. diff --git a/docs/framework/angular/reference/variables/unsetMarker.md b/docs/framework/angular/reference/variables/unsetMarker.md index c58e8465474..1a34fc7d2e0 100644 --- a/docs/framework/angular/reference/variables/unsetMarker.md +++ b/docs/framework/angular/reference/variables/unsetMarker.md @@ -4,7 +4,7 @@ title: unsetMarker --- ```ts -const unsetMarker: typeof unsetMarker; +const unsetMarker: unique symbol; ``` -Defined in: [packages/query-core/src/types.ts:92](https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L92) +Defined in: packages/query-core/dist-ts/src/types.d.ts:27 From 8771f3a9612cf6eb4ee936e6ee17cf69bf9a2524 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2026 11:09:41 +0000 Subject: [PATCH 9/9] ci: apply automated fixes --- .../guides/invalidations-from-mutations.md | 5 +- .../components/auto-refetching.component.ts | 5 +- .../optimistic-updates.component.ts | 5 +- .../src/app/components/example.component.ts | 5 +- .../src/devtools-panel/stub.ts | 6 +-- .../with-persist-query-client.test.ts | 50 +++++++++++-------- .../__tests__/inject-query-lifecycle.test.ts | 7 ++- .../src/__tests__/inject-query.test.ts | 1 - .../src/__tests__/with-hydration.test.ts | 30 ++++++----- .../angular-query/src/hydration-state-key.ts | 4 +- scripts/generate-docs.ts | 9 +--- 11 files changed, 63 insertions(+), 64 deletions(-) diff --git a/docs/framework/angular/guides/invalidations-from-mutations.md b/docs/framework/angular/guides/invalidations-from-mutations.md index a8e866224eb..dc92e619311 100644 --- a/docs/framework/angular/guides/invalidations-from-mutations.md +++ b/docs/framework/angular/guides/invalidations-from-mutations.md @@ -17,10 +17,7 @@ postTodoMutation = injectMutation(() => ({ [//]: # 'Example2' ```ts -import { - injectMutation, - QueryClient, -} from '@tanstack/angular-query' +import { injectMutation, QueryClient } from '@tanstack/angular-query' export class TodosComponent { readonly queryClient = inject(QueryClient) diff --git a/examples/angular/auto-refetching/src/app/components/auto-refetching.component.ts b/examples/angular/auto-refetching/src/app/components/auto-refetching.component.ts index 1838c357fd5..7a327005ebd 100644 --- a/examples/angular/auto-refetching/src/app/components/auto-refetching.component.ts +++ b/examples/angular/auto-refetching/src/app/components/auto-refetching.component.ts @@ -4,10 +4,7 @@ import { inject, signal, } from '@angular/core' -import { - injectMutation, - injectQuery, -} from '@tanstack/angular-query' +import { injectMutation, injectQuery } from '@tanstack/angular-query' import { NgStyle } from '@angular/common' import { TasksService } from '../services/tasks.service' diff --git a/examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts b/examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts index cbb01f0c0d5..42aa7d76773 100644 --- a/examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts +++ b/examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts @@ -1,8 +1,5 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core' -import { - injectMutation, - injectQuery, -} from '@tanstack/angular-query' +import { injectMutation, injectQuery } from '@tanstack/angular-query' import { FormsModule } from '@angular/forms' import { DatePipe } from '@angular/common' import { TasksService } from '../services/tasks.service' diff --git a/examples/angular/rxjs/src/app/components/example.component.ts b/examples/angular/rxjs/src/app/components/example.component.ts index e7aa3216215..d7bb20990fe 100644 --- a/examples/angular/rxjs/src/app/components/example.component.ts +++ b/examples/angular/rxjs/src/app/components/example.component.ts @@ -1,10 +1,7 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core' import { toSignal } from '@angular/core/rxjs-interop' import { NonNullableFormBuilder, ReactiveFormsModule } from '@angular/forms' -import { - injectQuery, - keepPreviousData, -} from '@tanstack/angular-query' +import { injectQuery, keepPreviousData } from '@tanstack/angular-query' import { debounceTime, distinctUntilChanged, lastValueFrom } from 'rxjs' import { AutocompleteService } from '../services/autocomplete-service' diff --git a/packages/angular-query-devtools/src/devtools-panel/stub.ts b/packages/angular-query-devtools/src/devtools-panel/stub.ts index 7da1608a6d5..3de12775c3c 100644 --- a/packages/angular-query-devtools/src/devtools-panel/stub.ts +++ b/packages/angular-query-devtools/src/devtools-panel/stub.ts @@ -10,8 +10,4 @@ export const injectDevtoolsPanel: InjectDevtoolsPanel = () => ({ destroy: noop, }) -export type { - InjectDevtoolsPanel, - DevtoolsPanelOptions, - DevtoolsPanelRef, -} +export type { InjectDevtoolsPanel, DevtoolsPanelOptions, DevtoolsPanelRef } diff --git a/packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts b/packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts index d46bfc1ee1e..3ec5bee36ff 100644 --- a/packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts +++ b/packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts @@ -170,14 +170,18 @@ describe('withPersistQueryClient', () => { > = [] const queryClient = new QueryClient() - void queryClient.query({ - queryKey: key1, - queryFn: () => sleep(10).then(() => 'hydrated-1'), - }).catch(noop) - void queryClient.query({ - queryKey: key2, - queryFn: () => sleep(10).then(() => 'hydrated-2'), - }).catch(noop) + void queryClient + .query({ + queryKey: key1, + queryFn: () => sleep(10).then(() => 'hydrated-1'), + }) + .catch(noop) + void queryClient + .query({ + queryKey: key2, + queryFn: () => sleep(10).then(() => 'hydrated-2'), + }) + .catch(noop) await vi.advanceTimersByTimeAsync(10) const persister = createMockPersister() @@ -504,10 +508,12 @@ describe('withPersistQueryClient', () => { it('should await onSuccess before refetching or subscribing', async () => { const key = queryKey() const queryClient = new QueryClient() - void queryClient.query({ - queryKey: key, - queryFn: () => sleep(10).then(() => 'hydrated'), - }).catch(noop) + void queryClient + .query({ + queryKey: key, + queryFn: () => sleep(10).then(() => 'hydrated'), + }) + .catch(noop) await vi.advanceTimersByTimeAsync(10) const persister = createMockPersister() @@ -696,10 +702,12 @@ describe('withPersistQueryClient', () => { ) const queryClient = new QueryClient() - void queryClient.query({ - queryKey: key, - queryFn: () => sleep(10).then(() => 'hydrated'), - }).catch(noop) + void queryClient + .query({ + queryKey: key, + queryFn: () => sleep(10).then(() => 'hydrated'), + }) + .catch(noop) await vi.advanceTimersByTimeAsync(10) persistQueryClientSave({ queryClient, persister: holder.persister }) @@ -779,10 +787,12 @@ describe('withPersistQueryClient', () => { .spyOn(persistClientCore, 'persistQueryClientSubscribe') .mockReturnValue(cleanup) - void queryClient.query({ - queryKey: key, - queryFn: () => sleep(10).then(() => 'hydrated'), - }).catch(noop) + void queryClient + .query({ + queryKey: key, + queryFn: () => sleep(10).then(() => 'hydrated'), + }) + .catch(noop) await vi.advanceTimersByTimeAsync(10) persistQueryClientSave({ queryClient, persister }) await vi.advanceTimersByTimeAsync(0) diff --git a/packages/angular-query/src/__tests__/inject-query-lifecycle.test.ts b/packages/angular-query/src/__tests__/inject-query-lifecycle.test.ts index 77f67a79744..e8825ac66a0 100644 --- a/packages/angular-query/src/__tests__/inject-query-lifecycle.test.ts +++ b/packages/angular-query/src/__tests__/inject-query-lifecycle.test.ts @@ -1,4 +1,9 @@ -import { DestroyRef, NgZone, PendingTasks, runInInjectionContext } from '@angular/core' +import { + DestroyRef, + NgZone, + PendingTasks, + runInInjectionContext, +} from '@angular/core' import { describe, expect, it, vi } from 'vitest' import { injectPendingTasksLifecycle } from '../utils/inject-pending-tasks-lifecycle' import type { Injector } from '@angular/core' diff --git a/packages/angular-query/src/__tests__/inject-query.test.ts b/packages/angular-query/src/__tests__/inject-query.test.ts index 29f082632e3..86a60a6fbd9 100644 --- a/packages/angular-query/src/__tests__/inject-query.test.ts +++ b/packages/angular-query/src/__tests__/inject-query.test.ts @@ -1351,7 +1351,6 @@ describe('injectQuery', () => { }).toThrowError(/NG0203(.*?)injectQuery/) }) - it('should complete queries before whenStable() resolves', async () => { const app = TestBed.inject(ApplicationRef) diff --git a/packages/angular-query/src/__tests__/with-hydration.test.ts b/packages/angular-query/src/__tests__/with-hydration.test.ts index bcdb30b91ea..ab5afe1c414 100644 --- a/packages/angular-query/src/__tests__/with-hydration.test.ts +++ b/packages/angular-query/src/__tests__/with-hydration.test.ts @@ -224,10 +224,12 @@ describe('TransferState dehydration (server)', () => { const queryClient = new QueryClient() const injector = createQueryInjector(queryClient, 'server') - void queryClient.query({ - queryKey: key, - queryFn: () => Promise.resolve('ssr-data'), - }).catch(noop) + void queryClient + .query({ + queryKey: key, + queryFn: () => Promise.resolve('ssr-data'), + }) + .catch(noop) await vi.advanceTimersByTimeAsync(0) injector.get(TransferState).toJson() @@ -246,10 +248,12 @@ describe('TransferState dehydration (server)', () => { const queryClient = new QueryClient() const injector = createQueryInjector(queryClient, 'browser') - void queryClient.query({ - queryKey: key, - queryFn: () => Promise.resolve('data'), - }).catch(noop) + void queryClient + .query({ + queryKey: key, + queryFn: () => Promise.resolve('data'), + }) + .catch(noop) await vi.advanceTimersByTimeAsync(0) injector.get(TransferState).toJson() @@ -270,10 +274,12 @@ describe('TransferState dehydration (server)', () => { withNoQueryHydration(), ) - void queryClient.query({ - queryKey: key, - queryFn: () => Promise.resolve('data'), - }).catch(noop) + void queryClient + .query({ + queryKey: key, + queryFn: () => Promise.resolve('data'), + }) + .catch(noop) await vi.advanceTimersByTimeAsync(0) injector.get(TransferState).toJson() diff --git a/packages/angular-query/src/hydration-state-key.ts b/packages/angular-query/src/hydration-state-key.ts index 0dd2c3ee2c9..3a1c4aeb327 100644 --- a/packages/angular-query/src/hydration-state-key.ts +++ b/packages/angular-query/src/hydration-state-key.ts @@ -1,5 +1,5 @@ -import { InjectionToken, makeStateKey } from '@angular/core' -import type {StateKey} from '@angular/core'; +import { InjectionToken, makeStateKey } from '@angular/core' +import type { StateKey } from '@angular/core' import type { DehydratedState } from '@tanstack/query-core' export const INTERNAL_TANSTACK_QUERY_HYDRATION_STATE_KEY = diff --git a/scripts/generate-docs.ts b/scripts/generate-docs.ts index e2d5cd8d74e..cc3d88bbe43 100644 --- a/scripts/generate-docs.ts +++ b/scripts/generate-docs.ts @@ -213,13 +213,8 @@ async function generatePackageReferenceDocs(pkg: PackageReferenceDocsConfig) { const packages: Array = [ { - entryPoints: [ - resolve(__dirname, '../packages/angular-query/src/index.ts'), - ], - tsconfig: resolve( - __dirname, - '../packages/angular-query/tsconfig.json', - ), + entryPoints: [resolve(__dirname, '../packages/angular-query/src/index.ts')], + tsconfig: resolve(__dirname, '../packages/angular-query/tsconfig.json'), outputDir: resolve(__dirname, '../docs/framework/angular/reference'), }, {