diff --git a/.github/labeler.yml b/.github/labeler.yml index 922ccaf298..001cb10a68 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,5 +1,3 @@ -'package: angular-query-devtools-experimental': - - 'packages/angular-query-devtools-experimental/**/*' 'package: angular-query-experimental': - 'packages/angular-query-experimental/**/*' 'package: eslint-plugin-query': diff --git a/codecov.yml b/codecov.yml index ef21589e00..da56c6458c 100644 --- a/codecov.yml +++ b/codecov.yml @@ -19,10 +19,6 @@ comment: component_management: individual_components: - - component_id: angular-query-devtools-experimental - name: '@tanstack/angular-query-devtools-experimental' - paths: - - packages/angular-query-devtools-experimental/** - component_id: angular-query-experimental name: '@tanstack/angular-query-experimental' paths: diff --git a/docs/framework/angular/devtools.md b/docs/framework/angular/devtools.md index 1787544ca1..eef761f6fe 100644 --- a/docs/framework/angular/devtools.md +++ b/docs/framework/angular/devtools.md @@ -7,27 +7,38 @@ title: Devtools The devtools help you debug and inspect your queries and mutations. You can enable the devtools by adding `withDevtools` to `provideTanStackQuery`. -By default, the devtools are enabled when Angular [`isDevMode`](https://angular.dev/api/core/isDevMode) returns true. So you don't need to worry about excluding them during a production build. The core tools are lazily loaded and excluded from bundled code. In most cases, all you'll need to do is add `withDevtools()` to `provideTanStackQuery` without any additional configuration. +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. ```ts import { QueryClient, provideTanStackQuery, - withDevtools, } from '@tanstack/angular-query-experimental' +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' + export const appConfig: ApplicationConfig = { providers: [provideTanStackQuery(new QueryClient(), withDevtools())], } ``` -## Configuring if devtools are loaded +## 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. + +```ts +import { withDevtools } from '@tanstack/angular-query-experimental/devtools/production' +``` -If you need more control over when devtools are loaded, you can use the `loadDevtools` option. This is particularly useful if you want to load devtools based on environment configurations. For instance, you might have a test environment running in production mode but still require devtools to be available. +To control when devtools are loaded, you can use the `loadDevtools` option. This is particularly useful if you want to load devtools based on environment configurations or user interaction. For instance, you might have a test environment running in production mode but still require devtools to be available. -When not setting the option or setting it to 'auto', the devtools will be loaded when Angular is in development mode. +When not setting the option or setting it to 'auto', the devtools will be loaded automatically when Angular runs in development mode. ```ts +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' + provideTanStackQuery(new QueryClient(), withDevtools()) // which is equivalent to @@ -39,7 +50,12 @@ provideTanStackQuery( When setting the option to true, the devtools will be loaded in both development and production mode. +This is particularly useful if you want to load devtools based on environment configurations. E.g. you could set this to true either when `isDevMode()` is true or when the application is running on your production build staging environment. + ```ts +// Make sure to use the production sub-path to load devtools in production builds +import { withDevtools } from '@tanstack/angular-query-experimental/devtools/production' + provideTanStackQuery( new QueryClient(), withDevtools(() => ({ loadDevtools: true })), @@ -55,44 +71,67 @@ provideTanStackQuery( ) ``` -The `withDevtools` options are returned from a callback function to support reactivity through signals. In the following example -a signal is created from a RxJS observable that listens for a keyboard shortcut. When the event is triggered, the devtools are lazily loaded. -Using this technique allows you to support on-demand loading of the devtools even in production mode, without including the full tools in the bundled code. +## Derive options through reactivity + +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. + +> If you don't need devtools in production builds, don't use the `production` sub-path. Even though most of the devtools are lazy loaded on-demand, code is needed for on-demand loading and option handling. When importing devtools from `@tanstack/angular-query-experimental/devtools`, all devtools code will be excluded from your build and no lazy chunks will be created, minimizing deployment size. + +The example below always loads devtools in development mode and loads on-demand in production mode when a keyboard shortcut is pressed. ```ts +import { Injectable, isDevMode } from '@angular/core' +import { fromEvent, map, scan } from 'rxjs' +import { toSignal } from '@angular/core/rxjs-interop' + @Injectable({ providedIn: 'root' }) -class DevtoolsOptionsManager { +export class DevtoolsOptionsManager { loadDevtools = toSignal( fromEvent(document, 'keydown').pipe( map( (event): boolean => event.metaKey && event.ctrlKey && event.shiftKey && event.key === 'D', ), - scan((acc, curr) => acc || curr, false), + scan((acc, curr) => acc || curr, isDevMode()), ), { - initialValue: false, + initialValue: isDevMode(), }, ) } +``` + +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. + +```ts +// ... +import { withDevtools } from '@tanstack/angular-query-experimental/devtools/production' export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(), provideTanStackQuery( new QueryClient(), - withDevtools(() => ({ - initialIsOpen: true, - loadDevtools: inject(DevtoolsOptionsManager).loadDevtools(), - })), + withDevtools( + (devToolsOptionsManager: DevtoolsOptionsManager) => ({ + loadDevtools: devToolsOptionsManager.loadDevtools(), + }), + { + // `deps` is used to inject and pass `DevtoolsOptionsManager` to the `withDevtools` callback. + deps: [DevtoolsOptionsManager], + }, + ), ), ], } ``` -### Options +### Options returned from the callback -Of these options `client`, `position`, `errorTypes`, `buttonPosition`, and `initialIsOpen` support reactivity through signals. +Of these options `loadDevtools`, `client`, `position`, `errorTypes`, `buttonPosition`, and `initialIsOpen` support reactivity through signals. - `loadDevtools?: 'auto' | boolean` - Defaults to `auto`: lazily loads devtools when in development mode. Skips loading in production mode. diff --git a/docs/framework/angular/reference/functions/withdevtools.md b/docs/framework/angular/reference/functions/withdevtools.md index 6dfdac2d77..b5e4e14d00 100644 --- a/docs/framework/angular/reference/functions/withdevtools.md +++ b/docs/framework/angular/reference/functions/withdevtools.md @@ -6,7 +6,7 @@ title: withDevtools # Function: withDevtools() ```ts -function withDevtools(withDevtoolsFn?): DeveloperToolsFeature +function withDevtools(withDevtoolsFn?): DevtoolsFeature ``` Enables developer tools. @@ -35,7 +35,7 @@ A function that returns `DevtoolsOptions`. ## Returns -[`DeveloperToolsFeature`](../../type-aliases/developertoolsfeature.md) +[`DevtoolsFeature`](../../type-aliases/developertoolsfeature.md) A set of providers for use with `provideTanStackQuery`. diff --git a/docs/framework/angular/reference/index.md b/docs/framework/angular/reference/index.md index c8b1690d3d..8dd0081367 100644 --- a/docs/framework/angular/reference/index.md +++ b/docs/framework/angular/reference/index.md @@ -35,7 +35,7 @@ title: '@tanstack/angular-query-experimental' - [DefinedCreateQueryResult](../type-aliases/definedcreatequeryresult.md) - [DefinedInitialDataInfiniteOptions](../type-aliases/definedinitialdatainfiniteoptions.md) - [DefinedInitialDataOptions](../type-aliases/definedinitialdataoptions.md) -- [DeveloperToolsFeature](../type-aliases/developertoolsfeature.md) +- [DevtoolsFeature](../type-aliases/developertoolsfeature.md) - [PersistQueryClientFeature](../type-aliases/persistqueryclientfeature.md) - [QueriesOptions](../type-aliases/queriesoptions.md) - [QueriesResults](../type-aliases/queriesresults.md) diff --git a/docs/framework/angular/reference/type-aliases/developertoolsfeature.md b/docs/framework/angular/reference/type-aliases/developertoolsfeature.md index ad4c952ff7..72c1227bd8 100644 --- a/docs/framework/angular/reference/type-aliases/developertoolsfeature.md +++ b/docs/framework/angular/reference/type-aliases/developertoolsfeature.md @@ -1,12 +1,12 @@ --- -id: DeveloperToolsFeature -title: DeveloperToolsFeature +id: DevtoolsFeature +title: DevtoolsFeature --- -# Type Alias: DeveloperToolsFeature +# Type Alias: DevtoolsFeature ```ts -type DeveloperToolsFeature = QueryFeature<'DeveloperTools'> +type DevtoolsFeature = QueryFeature<'DeveloperTools'> ``` A type alias that represents a feature which enables developer tools. diff --git a/docs/framework/angular/reference/type-aliases/queryfeatures.md b/docs/framework/angular/reference/type-aliases/queryfeatures.md index cb6a2eb82d..8278758878 100644 --- a/docs/framework/angular/reference/type-aliases/queryfeatures.md +++ b/docs/framework/angular/reference/type-aliases/queryfeatures.md @@ -6,7 +6,7 @@ title: QueryFeatures # Type Alias: QueryFeatures ```ts -type QueryFeatures = DeveloperToolsFeature | PersistQueryClientFeature +type QueryFeatures = DevtoolsFeature | PersistQueryClientFeature ``` A type alias that represents all Query features available for use with `provideTanStackQuery`. diff --git a/examples/angular/auto-refetching/src/app/app.config.ts b/examples/angular/auto-refetching/src/app/app.config.ts index 65a84a0c25..b9b2b6c36f 100644 --- a/examples/angular/auto-refetching/src/app/app.config.ts +++ b/examples/angular/auto-refetching/src/app/app.config.ts @@ -6,8 +6,8 @@ import { import { QueryClient, provideTanStackQuery, - withDevtools, } from '@tanstack/angular-query-experimental' +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' import { mockInterceptor } from './interceptor/mock-api.interceptor' import type { ApplicationConfig } from '@angular/core' diff --git a/examples/angular/basic-persister/src/app/app.config.ts b/examples/angular/basic-persister/src/app/app.config.ts index d449e21582..b563947609 100644 --- a/examples/angular/basic-persister/src/app/app.config.ts +++ b/examples/angular/basic-persister/src/app/app.config.ts @@ -2,10 +2,10 @@ import { provideHttpClient, withFetch } from '@angular/common/http' import { QueryClient, provideTanStackQuery, - withDevtools, } from '@tanstack/angular-query-experimental' import { withPersistQueryClient } from '@tanstack/angular-query-persist-client' import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister' +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' import type { ApplicationConfig } from '@angular/core' const localStoragePersister = createSyncStoragePersister({ diff --git a/examples/angular/basic/src/app/app.config.ts b/examples/angular/basic/src/app/app.config.ts index 700f4dc0a5..77281147d1 100644 --- a/examples/angular/basic/src/app/app.config.ts +++ b/examples/angular/basic/src/app/app.config.ts @@ -2,8 +2,8 @@ import { provideHttpClient, withFetch } from '@angular/common/http' import { QueryClient, provideTanStackQuery, - withDevtools, } from '@tanstack/angular-query-experimental' +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' import type { ApplicationConfig } from '@angular/core' export const appConfig: ApplicationConfig = { diff --git a/examples/angular/devtools-panel/package.json b/examples/angular/devtools-panel/package.json index 9cb9f4195f..6d897f9786 100644 --- a/examples/angular/devtools-panel/package.json +++ b/examples/angular/devtools-panel/package.json @@ -15,7 +15,6 @@ "@angular/platform-browser": "^20.0.0", "@angular/platform-browser-dynamic": "^20.0.0", "@angular/router": "^20.0.0", - "@tanstack/angular-query-devtools-experimental": "^5.80.8", "@tanstack/angular-query-experimental": "^5.80.8", "rxjs": "^7.8.2", "tslib": "^2.8.1", 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 7892d377c9..f0a56611eb 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-devtools-experimental' +import { injectDevtoolsPanel } from '@tanstack/angular-query-experimental/devtools-panel' import { ExampleQueryComponent } from './example-query.component' import type { ElementRef } from '@angular/core' 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 cd2366a4ce..9bb23b1192 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 @@ -10,7 +10,7 @@ import { } from '@angular/core' import { ExampleQueryComponent } from './example-query.component' import type { ElementRef } from '@angular/core' -import type { DevtoolsPanelRef } from '@tanstack/angular-query-devtools-experimental' +import type { DevtoolsPanelRef } from '@tanstack/angular-query-experimental/devtools-panel' @Component({ selector: 'lazy-load-devtools-panel-example', @@ -49,7 +49,7 @@ export default class LazyLoadDevtoolsPanelExampleComponent { if (this.devtools()) return if (this.isOpen()) { this.devtools.set( - import('@tanstack/angular-query-devtools-experimental').then( + import('@tanstack/angular-query-experimental/devtools-panel').then( ({ injectDevtoolsPanel }) => injectDevtoolsPanel(this.devToolsOptions, { injector: this.injector, 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 bd9b7a03d1..06854c4a7d 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 @@ -6,8 +6,8 @@ import { import { QueryClient, provideTanStackQuery, - withDevtools, } from '@tanstack/angular-query-experimental' +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' import { projectsMockInterceptor } from './api/projects-mock.interceptor' import type { ApplicationConfig } from '@angular/core' diff --git a/examples/angular/optimistic-updates/src/app/app.config.ts b/examples/angular/optimistic-updates/src/app/app.config.ts index 65a84a0c25..b9b2b6c36f 100644 --- a/examples/angular/optimistic-updates/src/app/app.config.ts +++ b/examples/angular/optimistic-updates/src/app/app.config.ts @@ -6,8 +6,8 @@ import { import { QueryClient, provideTanStackQuery, - withDevtools, } from '@tanstack/angular-query-experimental' +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' import { mockInterceptor } from './interceptor/mock-api.interceptor' import type { ApplicationConfig } from '@angular/core' diff --git a/examples/angular/pagination/src/app/app.config.ts b/examples/angular/pagination/src/app/app.config.ts index 919a81f92c..dc3189ba84 100644 --- a/examples/angular/pagination/src/app/app.config.ts +++ b/examples/angular/pagination/src/app/app.config.ts @@ -6,8 +6,8 @@ import { import { QueryClient, provideTanStackQuery, - withDevtools, } from '@tanstack/angular-query-experimental' +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' import { projectsMockInterceptor } from './api/projects-mock.interceptor' import type { ApplicationConfig } from '@angular/core' 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 7dd1d37236..dd6675f997 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 @@ -3,9 +3,9 @@ import { provideRouter, withComponentInputBinding } from '@angular/router' import { QueryClient, provideTanStackQuery, - withDevtools, } from '@tanstack/angular-query-experimental' +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' import { routes } from './app.routes' import type { ApplicationConfig } from '@angular/core' diff --git a/examples/angular/router/src/app/app.config.ts b/examples/angular/router/src/app/app.config.ts index de3234392a..3fbec800b1 100644 --- a/examples/angular/router/src/app/app.config.ts +++ b/examples/angular/router/src/app/app.config.ts @@ -3,9 +3,9 @@ import { provideRouter, withComponentInputBinding } from '@angular/router' import { QueryClient, provideTanStackQuery, - withDevtools, } from '@tanstack/angular-query-experimental' +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' import { routes } from './app.routes' import type { ApplicationConfig } from '@angular/core' diff --git a/examples/angular/rxjs/src/app/app.config.ts b/examples/angular/rxjs/src/app/app.config.ts index 36f8212a03..27eb15a53b 100644 --- a/examples/angular/rxjs/src/app/app.config.ts +++ b/examples/angular/rxjs/src/app/app.config.ts @@ -6,8 +6,8 @@ import { import { QueryClient, provideTanStackQuery, - withDevtools, } from '@tanstack/angular-query-experimental' +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' import { autocompleteMockInterceptor } from './api/autocomplete-mock.interceptor' import type { ApplicationConfig } from '@angular/core' diff --git a/examples/angular/simple/src/app/app.config.ts b/examples/angular/simple/src/app/app.config.ts index c4b9ca045e..9c7eda2597 100644 --- a/examples/angular/simple/src/app/app.config.ts +++ b/examples/angular/simple/src/app/app.config.ts @@ -2,8 +2,8 @@ import { provideHttpClient, withFetch } from '@angular/common/http' import { QueryClient, provideTanStackQuery, - withDevtools, } from '@tanstack/angular-query-experimental' +import { withDevtools } from '@tanstack/angular-query-experimental/devtools' import type { ApplicationConfig } from '@angular/core' export const appConfig: ApplicationConfig = { diff --git a/knip.json b/knip.json index c36c891ce7..bbce657376 100644 --- a/knip.json +++ b/knip.json @@ -14,6 +14,9 @@ ], "ignoreWorkspaces": ["examples/**", "integrations/**"], "workspaces": { + "packages/angular-query-experimental": { + "ignore": ["**/production/index.ts"] + }, "packages/query-codemods": { "entry": ["src/v4/**/*.cjs", "src/v5/**/*.cjs"], "ignore": ["**/__testfixtures__/**"] diff --git a/package.json b/package.json index c8896ea94c..1a705bbad6 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,6 @@ }, "pnpm": { "overrides": { - "@tanstack/angular-query-devtools-experimental": "workspace:*", "@tanstack/angular-query-experimental": "workspace:*", "@tanstack/eslint-plugin-query": "workspace:*", "@tanstack/query-async-storage-persister": "workspace:*", diff --git a/packages/angular-query-devtools-experimental/.attw.json b/packages/angular-query-devtools-experimental/.attw.json deleted file mode 100644 index 864f618c22..0000000000 --- a/packages/angular-query-devtools-experimental/.attw.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ignoreRules": [ - "cjs-resolves-to-esm", - "internal-resolution-error", - "no-resolution" - ] -} diff --git a/packages/angular-query-devtools-experimental/eslint.config.js b/packages/angular-query-devtools-experimental/eslint.config.js deleted file mode 100644 index 131737bfa0..0000000000 --- a/packages/angular-query-devtools-experimental/eslint.config.js +++ /dev/null @@ -1,17 +0,0 @@ -// @ts-check - -import pluginJsdoc from 'eslint-plugin-jsdoc' -import rootConfig from './root.eslint.config.js' - -export default [ - ...rootConfig, - pluginJsdoc.configs['flat/recommended-typescript'], - { - rules: { - 'jsdoc/require-hyphen-before-param-description': 1, - 'jsdoc/sort-tags': 1, - 'jsdoc/require-throws': 1, - 'jsdoc/check-tag-names': ['warn'], - }, - }, -] diff --git a/packages/angular-query-devtools-experimental/package.json b/packages/angular-query-devtools-experimental/package.json deleted file mode 100644 index b8ab89a07d..0000000000 --- a/packages/angular-query-devtools-experimental/package.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "name": "@tanstack/angular-query-devtools-experimental", - "version": "5.80.8", - "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-experimental" - }, - "homepage": "https://tanstack.com/query", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "scripts": { - "clean": "premove ./build ./coverage ./dist-ts", - "compile": "tsc --build", - "test:eslint": "eslint ./src", - "test:types": "npm-run-all --serial test:types:*", - "test:types:ts51": "node ../../node_modules/typescript51/lib/tsc.js --build", - "test:types:ts52": "node ../../node_modules/typescript52/lib/tsc.js --build", - "test:types:ts53": "node ../../node_modules/typescript53/lib/tsc.js --build", - "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js --build", - "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:tscurrent": "tsc --build", - "test:build": "publint --strict && attw --pack", - "build": "pnpm build:tsup", - "build:tsup": "tsup --tsconfig tsconfig.prod.json" - }, - "type": "module", - "types": "build/index.d.ts", - "module": "build/index.mjs", - "exports": { - ".": { - "@tanstack/custom-condition": "./src/index.ts", - "types": "./build/index.d.ts", - "default": "./build/index.mjs" - }, - "./package.json": { - "default": "./package.json" - } - }, - "sideEffects": false, - "files": [ - "build", - "src", - "!src/__tests__" - ], - "dependencies": { - "@tanstack/query-devtools": "workspace:*" - }, - "devDependencies": { - "@angular/core": "^20.0.0", - "@angular/platform-browser-dynamic": "^20.0.0", - "@tanstack/angular-query-experimental": "workspace:*", - "eslint-plugin-jsdoc": "^50.5.0", - "npm-run-all2": "^5.0.0" - }, - "peerDependencies": { - "@angular/common": ">=16.0.0", - "@angular/core": ">=16.0.0", - "@tanstack/angular-query-experimental": "workspace:^" - } -} diff --git a/packages/angular-query-devtools-experimental/root.eslint.config.js b/packages/angular-query-devtools-experimental/root.eslint.config.js deleted file mode 120000 index 35dedbe5a4..0000000000 --- a/packages/angular-query-devtools-experimental/root.eslint.config.js +++ /dev/null @@ -1 +0,0 @@ -../../eslint.config.js \ No newline at end of file diff --git a/packages/angular-query-devtools-experimental/src/index.ts b/packages/angular-query-devtools-experimental/src/index.ts deleted file mode 100644 index 82c19d6916..0000000000 --- a/packages/angular-query-devtools-experimental/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './inject-devtools-panel' diff --git a/packages/angular-query-devtools-experimental/src/test-setup.ts b/packages/angular-query-devtools-experimental/src/test-setup.ts deleted file mode 100644 index 30c962a8e6..0000000000 --- a/packages/angular-query-devtools-experimental/src/test-setup.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting, -} from '@angular/platform-browser-dynamic/testing' -import { getTestBed } from '@angular/core/testing' - -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), -) diff --git a/packages/angular-query-devtools-experimental/tsconfig.json b/packages/angular-query-devtools-experimental/tsconfig.json deleted file mode 100644 index 6e4428ba78..0000000000 --- a/packages/angular-query-devtools-experimental/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "./dist-ts", - "rootDir": ".", - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noFallthroughCasesInSwitch": true, - "useDefineForClassFields": false, - "target": "ES2022" - }, - "include": ["src", "*.config.js", "*.config.ts", "package.json"], - "references": [ - { "path": "../query-devtools" }, - { "path": "../angular-query-experimental" } - ] -} diff --git a/packages/angular-query-devtools-experimental/tsconfig.prod.json b/packages/angular-query-devtools-experimental/tsconfig.prod.json deleted file mode 100644 index 0f4c92da06..0000000000 --- a/packages/angular-query-devtools-experimental/tsconfig.prod.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "incremental": false, - "composite": false, - "rootDir": "../../" - } -} diff --git a/packages/angular-query-devtools-experimental/tsup.config.js b/packages/angular-query-devtools-experimental/tsup.config.js deleted file mode 100644 index a1e9d23c1c..0000000000 --- a/packages/angular-query-devtools-experimental/tsup.config.js +++ /dev/null @@ -1,13 +0,0 @@ -import { defineConfig } from 'tsup' - -export default defineConfig({ - entry: ['src/index.ts'], - sourcemap: true, - clean: true, - format: ['esm'], - dts: true, - outDir: 'build', - outExtension({ format }) { - return format === 'esm' ? { js: '.mjs' } : { js: '.js' } - }, -}) diff --git a/packages/angular-query-devtools-experimental/vite.config.ts b/packages/angular-query-devtools-experimental/vite.config.ts deleted file mode 100644 index 25fdba1056..0000000000 --- a/packages/angular-query-devtools-experimental/vite.config.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { defineConfig } from 'vitest/config' - -import packageJson from './package.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'], - }, - }, - }, - test: { - name: packageJson.name, - dir: './src', - watch: false, - environment: 'jsdom', - setupFiles: ['src/test-setup.ts'], - coverage: { enabled: true, provider: 'istanbul', include: ['src/**/*'] }, - typecheck: { enabled: true }, - globals: true, - restoreMocks: true, - }, -}) diff --git a/packages/angular-query-experimental/eslint.config.js b/packages/angular-query-experimental/eslint.config.js index a86775ff27..08acd3ac43 100644 --- a/packages/angular-query-experimental/eslint.config.js +++ b/packages/angular-query-experimental/eslint.config.js @@ -20,13 +20,7 @@ export default [ 'jsdoc/require-hyphen-before-param-description': 1, 'jsdoc/sort-tags': 1, 'jsdoc/require-throws': 1, - 'jsdoc/check-tag-names': [ - 'warn', - { - // Not compatible with Api Extractor @public - typed: false, - }, - ], + 'jsdoc/check-tag-names': ['warn'], }, }, { diff --git a/packages/angular-query-experimental/package.json b/packages/angular-query-experimental/package.json index bafbea5bf2..001a5c50d4 100644 --- a/packages/angular-query-experimental/package.json +++ b/packages/angular-query-experimental/package.json @@ -27,7 +27,7 @@ "tanstack" ], "scripts": { - "clean": "premove ./build ./coverage ./dist-ts ./**.d.ts", + "clean": "premove ./dist ./coverage ./dist-ts ./**.d.ts", "compile": "tsc --build", "test:eslint": "eslint ./src", "test:types": "npm-run-all --serial test:types:*", @@ -37,8 +37,8 @@ "test:types:ts53": "node ../../node_modules/typescript53/lib/tsc.js --build", "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js --build", "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:ts56": "node ../../node_modules/typescript56/lib/tsc.js --build", + "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --build", "test:types:tscurrent": "tsc --build", "test:lib": "vitest", "test:lib:dev": "pnpm run test:lib --watch", @@ -56,6 +56,24 @@ "@tanstack/custom-condition": "./src/index.ts", "default": "./dist/index.mjs" }, + "./devtools": { + "types": "./dist/types/devtools/index.d.ts", + "development": "./dist/devtools/index.mjs", + "default": "./dist/devtools/stub.mjs" + }, + "./devtools/production": { + "types": "./dist/types/devtools/production/index.d.ts", + "default": "./dist/devtools/index.mjs" + }, + "./devtools-panel": { + "types": "./dist/types/devtools-panel/index.d.ts", + "development": "./dist/devtools-panel/index.mjs", + "default": "./dist/devtools-panel/stub.mjs" + }, + "./devtools-panel/production": { + "types": "./dist/types/devtools-panel/production/index.d.ts", + "default": "./dist/devtools-panel/index.mjs" + }, "./package.json": { "default": "./package.json" } @@ -94,6 +112,24 @@ "types": "./index.d.ts", "default": "./dist/index.mjs" }, + "./devtools": { + "types": "./devtools/index.d.ts", + "development": "./dist/devtools/index.mjs", + "default": "./dist/devtools/stub.mjs" + }, + "./devtools/production": { + "types": "./devtools/production/index.d.ts", + "default": "./dist/devtools/index.mjs" + }, + "./devtools-panel": { + "types": "./devtools-panel/index.d.ts", + "development": "./dist/devtools-panel/index.mjs", + "default": "./dist/devtools-panel/stub.mjs" + }, + "./devtools-panel/production": { + "types": "./devtools-panel/production/index.d.ts", + "default": "./dist/devtools-panel/index.mjs" + }, "./package.json": { "default": "./package.json" } diff --git a/packages/angular-query-devtools-experimental/src/__tests__/inject-devtools-panel.test.ts b/packages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.ts similarity index 96% rename from packages/angular-query-devtools-experimental/src/__tests__/inject-devtools-panel.test.ts rename to packages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.ts index 367bb708f5..b18d2a3b34 100644 --- a/packages/angular-query-devtools-experimental/src/__tests__/inject-devtools-panel.test.ts +++ b/packages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.ts @@ -4,12 +4,10 @@ import { signal, } from '@angular/core' import { TestBed } from '@angular/core/testing' -import { - QueryClient, - provideTanStackQuery, -} from '@tanstack/angular-query-experimental' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { injectDevtoolsPanel } from '../inject-devtools-panel' +import { QueryClient } from '@tanstack/query-core' +import { provideTanStackQuery } from '../providers' +import { injectDevtoolsPanel } from '../devtools-panel' const mockDevtoolsPanelInstance = { mount: vi.fn(), diff --git a/packages/angular-query-experimental/src/__tests__/providers.test.ts b/packages/angular-query-experimental/src/__tests__/providers.test.ts index 929cf1ea34..e5f1177fa0 100644 --- a/packages/angular-query-experimental/src/__tests__/providers.test.ts +++ b/packages/angular-query-experimental/src/__tests__/providers.test.ts @@ -3,22 +3,21 @@ import { QueryClient } from '@tanstack/query-core' import { TestBed } from '@angular/core/testing' import { ENVIRONMENT_INITIALIZER, + EnvironmentInjector, + PLATFORM_ID, + createEnvironmentInjector, + isDevMode, provideZonelessChangeDetection, signal, } from '@angular/core' -import { isDevMode } from '../util/is-dev-mode/is-dev-mode' -import { provideTanStackQuery, withDevtools } from '../providers' -import type { DevtoolsOptions } from '../providers' -import type { Mock } from 'vitest' +import { provideTanStackQuery } from '../providers' +import { withDevtools } from '../devtools' import type { DevtoolsButtonPosition, DevtoolsErrorType, DevtoolsPosition, } from '@tanstack/query-devtools' - -vi.mock('../util/is-dev-mode/is-dev-mode', () => ({ - isDevMode: vi.fn(), -})) +import type { DevtoolsOptions } from '../devtools' const mockDevtoolsInstance = { mount: vi.fn(), @@ -36,12 +35,20 @@ vi.mock('@tanstack/query-devtools', () => ({ TanstackQueryDevtools: mockTanstackQueryDevtools, })) -describe('withDevtools feature', () => { - let isDevModeMock: Mock +vi.mock('@angular/core', async () => { + const actual = await vi.importActual('@angular/core') + return { + ...actual, + isDevMode: vi.fn(), + } +}) + +const mockIsDevMode = vi.mocked(isDevMode) +describe('withDevtools feature', () => { beforeEach(() => { + vi.clearAllMocks() vi.useFakeTimers() - isDevModeMock = isDevMode as Mock }) afterEach(() => { @@ -50,61 +57,59 @@ describe('withDevtools feature', () => { test.each([ { - description: - 'should provide developer tools in development mode by default', - isDevModeValue: true, + description: 'should load developer tools in development mode', + isDevMode: true, expectedCalled: true, }, { - description: - 'should not provide developer tools in production mode by default', - isDevModeValue: false, + description: 'should not load developer tools in production mode', + isDevMode: false, expectedCalled: false, }, { - description: `should provide developer tools in development mode when 'loadDeveloperTools' is set to 'auto'`, - isDevModeValue: true, + description: `should load developer tools in development mode when 'loadDevtools' is set to 'auto'`, + isDevMode: true, loadDevtools: 'auto', expectedCalled: true, }, { - description: `should not provide developer tools in production mode when 'loadDeveloperTools' is set to 'auto'`, - isDevModeValue: false, + description: `should not load developer tools in production mode when 'loadDevtools' is set to 'auto'`, + isDevMode: false, loadDevtools: 'auto', expectedCalled: false, }, { description: - "should provide developer tools in development mode when 'loadDevtools' is set to true", - isDevModeValue: true, + "should load developer tools in development mode when 'loadDevtools' is set to true", + isDevMode: true, loadDevtools: true, expectedCalled: true, }, { description: - "should provide developer tools in production mode when 'loadDevtools' is set to true", - isDevModeValue: false, + "should load developer tools in production mode when 'loadDevtools' is set to true", + isDevMode: false, loadDevtools: true, expectedCalled: true, }, { description: - "should not provide developer tools in development mode when 'loadDevtools' is set to false", - isDevModeValue: true, + "should not load developer tools in development mode when 'loadDevtools' is set to false", + isDevMode: true, loadDevtools: false, expectedCalled: false, }, { description: - "should not provide developer tools in production mode when 'loadDevtools' is set to false", - isDevModeValue: false, + "should not load developer tools in production mode when 'loadDevtools' is set to false", + isDevMode: false, loadDevtools: false, expectedCalled: false, }, ])( '$description', - async ({ isDevModeValue, loadDevtools, expectedCalled }) => { - isDevModeMock.mockReturnValue(isDevModeValue) + async ({ isDevMode: isDevModeValue, loadDevtools, expectedCalled }) => { + mockIsDevMode.mockReturnValue(isDevModeValue) const providers = [ provideZonelessChangeDetection(), @@ -127,6 +132,10 @@ describe('withDevtools feature', () => { TestBed.inject(ENVIRONMENT_INITIALIZER) await vi.runAllTimersAsync() + TestBed.tick() + await vi.dynamicImportSettled() + TestBed.tick() + await vi.dynamicImportSettled() if (expectedCalled) { expect(mockTanstackQueryDevtools).toHaveBeenCalled() @@ -136,6 +145,85 @@ describe('withDevtools feature', () => { }, ) + it('should not continue loading devtools after injector is destroyed', async () => { + TestBed.configureTestingModule({ + providers: [ + provideZonelessChangeDetection(), + provideTanStackQuery( + new QueryClient(), + withDevtools(() => ({ + loadDevtools: true, + })), + ), + ], + }) + + TestBed.inject(ENVIRONMENT_INITIALIZER) + // Destroys injector + TestBed.resetTestingModule() + await vi.runAllTimersAsync() + + expect(mockTanstackQueryDevtools).not.toHaveBeenCalled() + }) + + it('should not create devtools again when already provided', async () => { + TestBed.configureTestingModule({ + providers: [ + provideZonelessChangeDetection(), + provideTanStackQuery( + new QueryClient(), + withDevtools(() => ({ + loadDevtools: true, + })), + ), + ], + }) + + TestBed.inject(ENVIRONMENT_INITIALIZER) + await vi.runAllTimersAsync() + + expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1) + + const injector = TestBed.inject(EnvironmentInjector) + + createEnvironmentInjector( + [ + withDevtools(() => ({ + loadDevtools: true, + })).ɵproviders, + ], + injector, + ) + + TestBed.inject(ENVIRONMENT_INITIALIZER) + await vi.runAllTimersAsync() + + expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1) + }) + + it('should not load devtools if platform is not browser', async () => { + TestBed.configureTestingModule({ + providers: [ + { + provide: PLATFORM_ID, + useValue: 'server', + }, + provideZonelessChangeDetection(), + provideTanStackQuery( + new QueryClient(), + withDevtools(() => ({ + loadDevtools: true, + })), + ), + ], + }) + + TestBed.inject(ENVIRONMENT_INITIALIZER) + await vi.runAllTimersAsync() + + expect(mockTanstackQueryDevtools).not.toHaveBeenCalled() + }) + it('should update error types', async () => { const errorTypes = signal([] as Array) diff --git a/packages/angular-query-experimental/src/devtools-panel/index.ts b/packages/angular-query-experimental/src/devtools-panel/index.ts new file mode 100644 index 0000000000..2742a15469 --- /dev/null +++ b/packages/angular-query-experimental/src/devtools-panel/index.ts @@ -0,0 +1,8 @@ +export type { + InjectDevtoolsPanel, + DevtoolsPanelOptions, + InjectDevtoolsPanelOptions, + DevtoolsPanelRef, +} from './types' + +export { injectDevtoolsPanel } from './inject-devtools-panel' diff --git a/packages/angular-query-devtools-experimental/src/inject-devtools-panel.ts b/packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts similarity index 60% rename from packages/angular-query-devtools-experimental/src/inject-devtools-panel.ts rename to packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts index 0fdff618fc..71ac82e5ad 100644 --- a/packages/angular-query-devtools-experimental/src/inject-devtools-panel.ts +++ b/packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts @@ -10,22 +10,13 @@ import { untracked, } from '@angular/core' import { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools' -import { - QueryClient, - onlineManager, -} from '@tanstack/angular-query-experimental' +import { QueryClient, onlineManager } from '@tanstack/query-core' import { isPlatformBrowser } from '@angular/common' -import type { ElementRef } from '@angular/core' -import type { DevtoolsErrorType } from '@tanstack/query-devtools' - -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 -} +import type { + DevtoolsPanelOptions, + InjectDevtoolsPanel, + InjectDevtoolsPanelOptions, +} from './types' /** * Inject a TanStack Query devtools panel and render it in the DOM. @@ -39,10 +30,10 @@ export interface InjectDevtoolsPanelOptions { * @returns DevtoolsPanelRef * @see https://tanstack.com/query/v5/docs/framework/angular/devtools */ -export function injectDevtoolsPanel( +export const injectDevtoolsPanel: InjectDevtoolsPanel = ( injectDevtoolsPanelFn: () => DevtoolsPanelOptions, options?: InjectDevtoolsPanelOptions, -): DevtoolsPanelRef { +) => { !options?.injector && assertInInjectionContext(injectDevtoolsPanel) const currentInjector = options?.injector ?? inject(Injector) @@ -108,43 +99,3 @@ export function injectDevtoolsPanel( } }) } - -/** - * A devtools panel, which can be manually destroyed. - */ -export interface DevtoolsPanelRef { - /** - * Destroy the panel, removing it from the DOM and stops listening to signal changes. - */ - destroy: () => void -} - -export interface DevtoolsPanelOptions { - /** - * 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 specific element in the DOM. - */ - shadowDOMTarget?: ShadowRoot - - /** - * Callback function that is called when the devtools panel is closed - */ - 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 -} diff --git a/packages/angular-query-experimental/src/devtools-panel/production/index.ts b/packages/angular-query-experimental/src/devtools-panel/production/index.ts new file mode 100644 index 0000000000..546becea7f --- /dev/null +++ b/packages/angular-query-experimental/src/devtools-panel/production/index.ts @@ -0,0 +1 @@ +export * from '..' diff --git a/packages/angular-query-experimental/src/devtools-panel/stub.ts b/packages/angular-query-experimental/src/devtools-panel/stub.ts new file mode 100644 index 0000000000..63e836eb5c --- /dev/null +++ b/packages/angular-query-experimental/src/devtools-panel/stub.ts @@ -0,0 +1,7 @@ +import { noop } from '@tanstack/query-core' +import type { InjectDevtoolsPanel } from './types' + +// Stub which replaces `injectDevtoolsPanel` in production builds +export const injectDevtoolsPanel: InjectDevtoolsPanel = () => ({ + destroy: noop, +}) diff --git a/packages/angular-query-experimental/src/devtools-panel/types.ts b/packages/angular-query-experimental/src/devtools-panel/types.ts new file mode 100644 index 0000000000..b87373ad95 --- /dev/null +++ b/packages/angular-query-experimental/src/devtools-panel/types.ts @@ -0,0 +1,57 @@ +import type { DevtoolsErrorType } from '@tanstack/query-devtools' +import type { ElementRef, Injector } 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. + */ +export interface DevtoolsPanelRef { + /** + * Destroy the panel, removing it from the DOM and stops listening to signal changes. + */ + destroy: () => void +} + +export interface DevtoolsPanelOptions { + /** + * 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 specific element in the DOM. + */ + shadowDOMTarget?: ShadowRoot + + /** + * Callback function that is called when the devtools panel is closed + */ + 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 +} + +export type InjectDevtoolsPanel = ( + injectDevtoolsPanelFn: () => DevtoolsPanelOptions, + options?: InjectDevtoolsPanelOptions, +) => DevtoolsPanelRef diff --git a/packages/angular-query-experimental/src/devtools/index.ts b/packages/angular-query-experimental/src/devtools/index.ts new file mode 100644 index 0000000000..d4f7e9238f --- /dev/null +++ b/packages/angular-query-experimental/src/devtools/index.ts @@ -0,0 +1,8 @@ +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 new file mode 100644 index 0000000000..546becea7f --- /dev/null +++ b/packages/angular-query-experimental/src/devtools/production/index.ts @@ -0,0 +1 @@ +export * from '..' diff --git a/packages/angular-query-experimental/src/devtools/stub.ts b/packages/angular-query-experimental/src/devtools/stub.ts new file mode 100644 index 0000000000..d8090a4b28 --- /dev/null +++ b/packages/angular-query-experimental/src/devtools/stub.ts @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000000..79ea7d77c6 --- /dev/null +++ b/packages/angular-query-experimental/src/devtools/types.ts @@ -0,0 +1,103 @@ +import type { QueryClient } from '@tanstack/query-core' +import type { + DevtoolsButtonPosition, + DevtoolsErrorType, + DevtoolsPosition, +} 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` + * Defaults to `bottom-right`. + */ + buttonPosition?: DevtoolsButtonPosition + /** + * The position of the TanStack Query devtools panel. + * `top` | `bottom` | `left` | `right` + * Defaults to `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 + + /** + * 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 new file mode 100644 index 0000000000..1212804442 --- /dev/null +++ b/packages/angular-query-experimental/src/devtools/with-devtools.ts @@ -0,0 +1,173 @@ +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, + } = 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) + return + } + + // Create devtools + import('@tanstack/query-devtools').then((queryDevtools) => { + // As this code runs async, injector can be destroyed in the meantime + 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) + }) + }, + { injector }, + ) + } + }, + }, + ]) diff --git a/packages/angular-query-experimental/src/index.ts b/packages/angular-query-experimental/src/index.ts index 360be005e6..edc45c9b6a 100644 --- a/packages/angular-query-experimental/src/index.ts +++ b/packages/angular-query-experimental/src/index.ts @@ -48,17 +48,14 @@ export { injectQuery } from './inject-query' export { injectQueryClient } from './inject-query-client' export type { - DeveloperToolsFeature, - DevtoolsOptions, + DevtoolsFeature, PersistQueryClientFeature, QueryFeature, - QueryFeatureKind, QueryFeatures, } from './providers' export { + provideAngularQuery, provideQueryClient, provideTanStackQuery, queryFeature, - queryFeatures, - withDevtools, } from './providers' diff --git a/packages/angular-query-experimental/src/infinite-query-options.ts b/packages/angular-query-experimental/src/infinite-query-options.ts index fdc7396c99..fc18c0e94d 100644 --- a/packages/angular-query-experimental/src/infinite-query-options.ts +++ b/packages/angular-query-experimental/src/infinite-query-options.ts @@ -84,7 +84,6 @@ export type DefinedInitialDataInfiniteOptions< * The `queryKey` will be tagged with the type from `queryFn`. * @param options - The infinite query options to tag with the type from `queryFn`. * @returns The tagged infinite query options. - * @public */ export function infiniteQueryOptions< TQueryFnData, @@ -116,7 +115,6 @@ export function infiniteQueryOptions< * The `queryKey` will be tagged with the type from `queryFn`. * @param options - The infinite query options to tag with the type from `queryFn`. * @returns The tagged infinite query options. - * @public */ export function infiniteQueryOptions< TQueryFnData, @@ -148,7 +146,6 @@ export function infiniteQueryOptions< * The `queryKey` will be tagged with the type from `queryFn`. * @param options - The infinite query options to tag with the type from `queryFn`. * @returns The tagged infinite query options. - * @public */ export function infiniteQueryOptions< TQueryFnData, @@ -180,7 +177,6 @@ export function infiniteQueryOptions< * The `queryKey` will be tagged with the type from `queryFn`. * @param options - The infinite query options to tag with the type from `queryFn`. * @returns The tagged infinite query options. - * @public */ export function infiniteQueryOptions(options: unknown) { return options diff --git a/packages/angular-query-experimental/src/inject-infinite-query.ts b/packages/angular-query-experimental/src/inject-infinite-query.ts index 6df26a0bb5..ee6de03240 100644 --- a/packages/angular-query-experimental/src/inject-infinite-query.ts +++ b/packages/angular-query-experimental/src/inject-infinite-query.ts @@ -37,7 +37,6 @@ export interface InjectInfiniteQueryOptions { * @param injectInfiniteQueryFn - A function that returns infinite query options. * @param options - Additional configuration. * @returns The infinite query result. - * @public */ export function injectInfiniteQuery< TQueryFnData, @@ -62,7 +61,6 @@ export function injectInfiniteQuery< * @param injectInfiniteQueryFn - A function that returns infinite query options. * @param options - Additional configuration. * @returns The infinite query result. - * @public */ export function injectInfiniteQuery< TQueryFnData, @@ -87,7 +85,6 @@ export function injectInfiniteQuery< * @param injectInfiniteQueryFn - A function that returns infinite query options. * @param options - Additional configuration. * @returns The infinite query result. - * @public */ export function injectInfiniteQuery< TQueryFnData, @@ -112,7 +109,6 @@ export function injectInfiniteQuery< * @param injectInfiniteQueryFn - A function that returns infinite query options. * @param options - Additional configuration. * @returns The infinite query result. - * @public */ export function injectInfiniteQuery( injectInfiniteQueryFn: () => CreateInfiniteQueryOptions, diff --git a/packages/angular-query-experimental/src/inject-is-mutating.ts b/packages/angular-query-experimental/src/inject-is-mutating.ts index 21de13b90e..8f11291b0e 100644 --- a/packages/angular-query-experimental/src/inject-is-mutating.ts +++ b/packages/angular-query-experimental/src/inject-is-mutating.ts @@ -26,7 +26,6 @@ export interface InjectIsMutatingOptions { * @param filters - The filters to apply to the query. * @param options - Additional configuration * @returns signal with number of fetching mutations. - * @public */ export function injectIsMutating( filters?: MutationFilters, diff --git a/packages/angular-query-experimental/src/inject-is-restoring.ts b/packages/angular-query-experimental/src/inject-is-restoring.ts index 92e50d4342..2c7fb3ae68 100644 --- a/packages/angular-query-experimental/src/inject-is-restoring.ts +++ b/packages/angular-query-experimental/src/inject-is-restoring.ts @@ -7,30 +7,27 @@ import { } from '@angular/core' import type { Provider, Signal } from '@angular/core' -const IS_RESTORING = new InjectionToken( - typeof ngDevMode === 'undefined' || ngDevMode - ? 'TANSTACK_QUERY_IS_RESTORING' - : '', - { - // Default value when not provided - factory: () => signal(false).asReadonly(), - }, -) - /** - * The `Injector` in which to create the isRestoring signal. - * - * If this is not provided, the current injection context will be used instead (via `inject`). + * 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 is currently in progress. {@link injectQuery} and friends also check this internally to avoid race conditions between the restore and initializing queries. * @param options - Options for injectIsRestoring. - * @returns signal with boolean that indicates whether a restore is in progress. - * @public + * @returns readonly signal with boolean that indicates whether a restore is in progress. */ export function injectIsRestoring(options?: InjectIsRestoringOptions) { !options?.injector && assertInInjectionContext(injectIsRestoring) @@ -42,7 +39,6 @@ export function injectIsRestoring(options?: InjectIsRestoringOptions) { * Used by TanStack Query Angular persist client plugin to provide the signal that tracks the restore state * @param isRestoring - a readonly signal that returns a boolean * @returns Provider for the `isRestoring` signal - * @public */ export function provideIsRestoring(isRestoring: Signal): Provider { return { diff --git a/packages/angular-query-experimental/src/inject-mutation-state.ts b/packages/angular-query-experimental/src/inject-mutation-state.ts index 89419f1037..5f8996b2b1 100644 --- a/packages/angular-query-experimental/src/inject-mutation-state.ts +++ b/packages/angular-query-experimental/src/inject-mutation-state.ts @@ -42,9 +42,6 @@ function getResult( ) } -/** - * @public - */ export interface InjectMutationStateOptions { /** * The `Injector` in which to create the mutation state signal. @@ -59,7 +56,6 @@ export interface InjectMutationStateOptions { * @param injectMutationStateFn - A function that returns mutation state options. * @param options - The Angular injector to use. * @returns The signal that tracks the state of all mutations. - * @public */ export function injectMutationState( injectMutationStateFn: () => MutationStateOptions = () => ({}), diff --git a/packages/angular-query-experimental/src/inject-mutation.ts b/packages/angular-query-experimental/src/inject-mutation.ts index 2cb465104f..a2a29c70e8 100644 --- a/packages/angular-query-experimental/src/inject-mutation.ts +++ b/packages/angular-query-experimental/src/inject-mutation.ts @@ -37,7 +37,6 @@ export interface InjectMutationOptions { * @param injectMutationFn - A function that returns mutation options. * @param options - Additional configuration * @returns The mutation. - * @public */ export function injectMutation< TData = unknown, diff --git a/packages/angular-query-experimental/src/inject-queries.ts b/packages/angular-query-experimental/src/inject-queries.ts index 1889e9560c..0cbcf3fb6a 100644 --- a/packages/angular-query-experimental/src/inject-queries.ts +++ b/packages/angular-query-experimental/src/inject-queries.ts @@ -116,7 +116,6 @@ type GetResults = /** * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param - * @public */ export type QueriesOptions< T extends Array, @@ -159,7 +158,6 @@ export type QueriesOptions< /** * QueriesResults reducer recursively maps type param to results - * @public */ export type QueriesResults< T extends Array, @@ -200,8 +198,6 @@ export type QueriesResults< * @param root0.queries * @param root0.combine * @param injector - * @param injector - * @public */ export function injectQueries< T extends Array, diff --git a/packages/angular-query-experimental/src/inject-query-client.ts b/packages/angular-query-experimental/src/inject-query-client.ts index 3ac28e4d5e..7cd29e3850 100644 --- a/packages/angular-query-experimental/src/inject-query-client.ts +++ b/packages/angular-query-experimental/src/inject-query-client.ts @@ -6,7 +6,6 @@ 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. - * @public * @deprecated Use `inject(QueryClient)` instead. * If you need to get a `QueryClient` from a custom injector, use `injector.get(QueryClient)`. * diff --git a/packages/angular-query-experimental/src/inject-query.ts b/packages/angular-query-experimental/src/inject-query.ts index 0defdf18e9..1dac0ab694 100644 --- a/packages/angular-query-experimental/src/inject-query.ts +++ b/packages/angular-query-experimental/src/inject-query.ts @@ -60,7 +60,6 @@ export interface InjectQueryOptions { * @param injectQueryFn - A function that returns query options. * @param options - Additional configuration * @returns The query result. - * @public * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries */ export function injectQuery< @@ -112,7 +111,6 @@ export function injectQuery< * @param injectQueryFn - A function that returns query options. * @param options - Additional configuration * @returns The query result. - * @public * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries */ export function injectQuery< @@ -164,7 +162,6 @@ export function injectQuery< * @param injectQueryFn - A function that returns query options. * @param options - Additional configuration * @returns The query result. - * @public * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries */ export function injectQuery< @@ -216,7 +213,6 @@ export function injectQuery< * @param injectQueryFn - A function that returns query options. * @param options - Additional configuration * @returns The query result. - * @public * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries */ export function injectQuery( diff --git a/packages/angular-query-experimental/src/mutation-options.ts b/packages/angular-query-experimental/src/mutation-options.ts index b55f0367db..6e8f9b43ef 100644 --- a/packages/angular-query-experimental/src/mutation-options.ts +++ b/packages/angular-query-experimental/src/mutation-options.ts @@ -33,7 +33,6 @@ import type { * ``` * @param options - The mutation options. * @returns Mutation options. - * @public */ export function mutationOptions< TData = unknown, @@ -46,9 +45,6 @@ export function mutationOptions< return options } -/** - * @public - */ export interface CreateMutationOptions< TData = unknown, TError = DefaultError, diff --git a/packages/angular-query-experimental/src/providers.ts b/packages/angular-query-experimental/src/providers.ts index d7619cec71..076d76d0c3 100644 --- a/packages/angular-query-experimental/src/providers.ts +++ b/packages/angular-query-experimental/src/providers.ts @@ -1,22 +1,6 @@ -import { - DestroyRef, - ENVIRONMENT_INITIALIZER, - InjectionToken, - PLATFORM_ID, - computed, - effect, - inject, -} from '@angular/core' -import { QueryClient, noop, onlineManager } from '@tanstack/query-core' -import { isPlatformBrowser } from '@angular/common' -import { isDevMode } from './util/is-dev-mode/is-dev-mode' +import { DestroyRef, InjectionToken, inject } from '@angular/core' +import { QueryClient } from '@tanstack/query-core' import type { Provider } from '@angular/core' -import type { - DevtoolsButtonPosition, - DevtoolsErrorType, - DevtoolsPosition, - TanstackQueryDevtools, -} from '@tanstack/query-devtools' /** * Usually {@link provideTanStackQuery} is used once to set up TanStack Query and the @@ -108,6 +92,10 @@ export function provideQueryClient( * // In a lazy loaded route or lazy loaded component's providers array: * providers: [provideTanStackQuery(MY_QUERY_CLIENT)] * ``` + * Using an InjectionToken for the QueryClient is an advanced optimization which allows TanStack Query to be absent from the main application bundle. + * This can be beneficial if you want to include TanStack Query on lazy loaded routes only while still sharing a `QueryClient`. + * + * Note that this is a small optimization and for most applications it's preferable to provide the `QueryClient` in the main application config. * @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. @@ -130,7 +118,6 @@ export function provideTanStackQuery( * Allows to configure a `QueryClient`. * @param queryClient - A `QueryClient` instance. * @returns A set of providers to set up TanStack Query. - * @public * @see https://tanstack.com/query/v5/docs/framework/angular/quick-start * @deprecated Use `provideTanStackQuery` instead. */ @@ -138,6 +125,10 @@ 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. */ @@ -162,207 +153,21 @@ export function queryFeature( /** * A type alias that represents a feature which enables developer tools. * The type is used to describe the return value of the `withDevtools` function. - * @public * @see {@link withDevtools} */ -export type DeveloperToolsFeature = QueryFeature<'DeveloperTools'> +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. - * @public */ export type PersistQueryClientFeature = QueryFeature<'PersistQueryClient'> -/** - * Options for configuring the TanStack Query devtools. - * @public - */ -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` - * Defaults to `bottom-right`. - */ - buttonPosition?: DevtoolsButtonPosition - /** - * The position of the TanStack Query devtools panel. - * `top` | `bottom` | `left` | `right` - * Defaults to `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 - - /** - * 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 -} - -/** - * Enables developer tools. - * - * **Example** - * - * ```ts - * export const appConfig: ApplicationConfig = { - * providers: [ - * provideTanStackQuery(new QueryClient(), withDevtools()) - * ] - * } - * ``` - * By default the devtools will be loaded when Angular runs in development mode and rendered in ``. - * - * If you need more control over when devtools are loaded, you can use the `loadDevtools` option. This is particularly useful if you want to load devtools based on environment configurations. For instance, you might have a test environment running in production mode but still require devtools to be available. - * - * 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`. - * @returns A set of providers for use with `provideTanStackQuery`. - * @public - * @see {@link provideTanStackQuery} - * @see {@link DevtoolsOptions} - */ -export function withDevtools( - withDevtoolsFn?: () => DevtoolsOptions, -): DeveloperToolsFeature { - let providers: Array = [] - if (!isDevMode() && !withDevtoolsFn) { - providers = [] - } else { - providers = [ - { - // Do not use provideEnvironmentInitializer while Angular < v19 is supported - provide: ENVIRONMENT_INITIALIZER, - multi: true, - useFactory: () => { - if (!isPlatformBrowser(inject(PLATFORM_ID))) return noop - const injectedClient = inject(QueryClient, { - optional: true, - }) - const destroyRef = inject(DestroyRef) - - const options = computed(() => withDevtoolsFn?.() ?? {}) - - let devtools: TanstackQueryDevtools | null = null - let el: HTMLElement | null = null - - const shouldLoadToolsSignal = computed(() => { - const { loadDevtools } = options() - return typeof loadDevtools === 'boolean' - ? loadDevtools - : isDevMode() - }) - - const getResolvedQueryClient = () => { - const client = options().client ?? injectedClient - if (!client) { - throw new Error('No QueryClient found') - } - return client - } - - const destroyDevtools = () => { - devtools?.unmount() - el?.remove() - devtools = null - } - - return () => - effect(() => { - const shouldLoadTools = shouldLoadToolsSignal() - const { - client, - position, - errorTypes, - buttonPosition, - initialIsOpen, - } = options() - - if (devtools && !shouldLoadTools) { - destroyDevtools() - return - } else if (devtools && shouldLoadTools) { - client && devtools.setClient(client) - position && devtools.setPosition(position) - errorTypes && devtools.setErrorTypes(errorTypes) - buttonPosition && devtools.setButtonPosition(buttonPosition) - initialIsOpen && devtools.setInitialIsOpen(initialIsOpen) - return - } else if (!shouldLoadTools) { - return - } - - el = document.body.appendChild(document.createElement('div')) - el.classList.add('tsqd-parent-container') - - import('@tanstack/query-devtools').then((queryDevtools) => { - devtools = new queryDevtools.TanstackQueryDevtools({ - ...options(), - client: getResolvedQueryClient(), - queryFlavor: 'Angular Query', - version: '5', - onlineManager, - }) - - el && devtools.mount(el) - - // Unmount the devtools on application destroy - destroyRef.onDestroy(destroyDevtools) - }) - }) - }, - }, - ] - } - return queryFeature('DeveloperTools', providers) -} - /** * 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. - * @public * @see {@link provideTanStackQuery} */ -export type QueryFeatures = DeveloperToolsFeature | PersistQueryClientFeature - -export const queryFeatures = ['DeveloperTools', 'PersistQueryClient'] as const - -export type QueryFeatureKind = (typeof queryFeatures)[number] +export type QueryFeatures = DevtoolsFeature | PersistQueryClientFeature diff --git a/packages/angular-query-experimental/src/query-options.ts b/packages/angular-query-experimental/src/query-options.ts index e82540bee5..069472b903 100644 --- a/packages/angular-query-experimental/src/query-options.ts +++ b/packages/angular-query-experimental/src/query-options.ts @@ -72,7 +72,6 @@ export type DefinedInitialDataOptions< * ``` * @param options - The query options to tag with the type from `queryFn`. * @returns The tagged query options. - * @public */ export function queryOptions< TQueryFnData = unknown, @@ -105,7 +104,6 @@ export function queryOptions< * ``` * @param options - The query options to tag with the type from `queryFn`. * @returns The tagged query options. - * @public */ export function queryOptions< TQueryFnData = unknown, @@ -138,7 +136,6 @@ export function queryOptions< * ``` * @param options - The query options to tag with the type from `queryFn`. * @returns The tagged query options. - * @public */ export function queryOptions< TQueryFnData = unknown, @@ -171,7 +168,6 @@ export function queryOptions< * ``` * @param options - The query options to tag with the type from `queryFn`. * @returns The tagged query options. - * @public */ export function queryOptions(options: unknown) { return options diff --git a/packages/angular-query-experimental/src/types.ts b/packages/angular-query-experimental/src/types.ts index 578eaa0864..e32b8b8585 100644 --- a/packages/angular-query-experimental/src/types.ts +++ b/packages/angular-query-experimental/src/types.ts @@ -17,9 +17,6 @@ import type { import type { Signal } from '@angular/core' import type { MapToSignals } from './signal-proxy' -/** - * @public - */ export interface CreateBaseQueryOptions< TQueryFnData = unknown, TError = DefaultError, @@ -34,9 +31,6 @@ export interface CreateBaseQueryOptions< TQueryKey > {} -/** - * @public - */ export interface CreateQueryOptions< TQueryFnData = unknown, TError = DefaultError, @@ -53,18 +47,12 @@ export interface CreateQueryOptions< 'suspense' > {} -/** - * @public - */ type CreateStatusBasedQueryResult< TStatus extends QueryObserverResult['status'], TData = unknown, TError = DefaultError, > = Extract, { status: TStatus }> -/** - * @public - */ export interface BaseQueryNarrowing { isSuccess: ( this: CreateBaseQueryResult, @@ -89,9 +77,6 @@ export interface BaseQueryNarrowing { > } -/** - * @public - */ export interface CreateInfiniteQueryOptions< TQueryFnData = unknown, TError = DefaultError, @@ -109,9 +94,6 @@ export interface CreateInfiniteQueryOptions< 'suspense' > {} -/** - * @public - */ export type CreateBaseQueryResult< TData = unknown, TError = DefaultError, @@ -119,17 +101,11 @@ export type CreateBaseQueryResult< > = BaseQueryNarrowing & MapToSignals> -/** - * @public - */ export type CreateQueryResult< TData = unknown, TError = DefaultError, > = CreateBaseQueryResult -/** - * @public - */ export type DefinedCreateQueryResult< TData = unknown, TError = DefaultError, @@ -137,18 +113,12 @@ export type DefinedCreateQueryResult< > = BaseQueryNarrowing & MapToSignals> -/** - * @public - */ export type CreateInfiniteQueryResult< TData = unknown, TError = DefaultError, > = BaseQueryNarrowing & MapToSignals> -/** - * @public - */ export type DefinedCreateInfiniteQueryResult< TData = unknown, TError = DefaultError, @@ -158,9 +128,6 @@ export type DefinedCreateInfiniteQueryResult< >, > = MapToSignals -/** - * @public - */ export type CreateMutateFunction< TData = unknown, TError = DefaultError, @@ -170,9 +137,6 @@ export type CreateMutateFunction< ...args: Parameters> ) => void -/** - * @public - */ export type CreateMutateAsyncFunction< TData = unknown, TError = DefaultError, @@ -180,9 +144,6 @@ export type CreateMutateAsyncFunction< TContext = unknown, > = MutateFunction -/** - * @public - */ export type CreateBaseMutationResult< TData = unknown, TError = DefaultError, @@ -195,9 +156,6 @@ export type CreateBaseMutationResult< mutateAsync: CreateMutateAsyncFunction } -/** - * @public - */ type CreateStatusBasedMutationResult< TStatus extends CreateBaseMutationResult['status'], TData = unknown, @@ -211,9 +169,6 @@ type CreateStatusBasedMutationResult< type SignalFunction any> = T & Signal> -/** - * @public - */ export interface BaseMutationNarrowing< TData = unknown, TError = DefaultError, @@ -290,9 +245,6 @@ export interface BaseMutationNarrowing< > } -/** - * @public - */ export type CreateMutationResult< TData = unknown, TError = DefaultError, diff --git a/packages/angular-query-experimental/src/util/is-dev-mode/is-dev-mode.ts b/packages/angular-query-experimental/src/util/is-dev-mode/is-dev-mode.ts deleted file mode 100644 index 5c18cfcf51..0000000000 --- a/packages/angular-query-experimental/src/util/is-dev-mode/is-dev-mode.ts +++ /dev/null @@ -1,3 +0,0 @@ -// Re-export for mocking in tests - -export { isDevMode } from '@angular/core' diff --git a/packages/angular-query-experimental/vite.config.ts b/packages/angular-query-experimental/vite.config.ts index 25eb7d8c68..1ba81961f9 100644 --- a/packages/angular-query-experimental/vite.config.ts +++ b/packages/angular-query-experimental/vite.config.ts @@ -76,8 +76,6 @@ export const tanstackViteConfig = (options: Options) => { declarationMap: false, }, beforeWriteFile: (filePath, content) => { - // content = - // options.beforeWriteDeclarationFile?.(filePath, content) || content return { filePath, content: ensureImportFileExtension({ content, extension: 'js' }), @@ -114,7 +112,13 @@ export default mergeConfig( config, tanstackViteConfig({ cjs: false, - entry: ['./src/index.ts'], + entry: [ + './src/index.ts', + './src/devtools-panel/index.ts', + './src/devtools-panel/stub.ts', + './src/devtools/index.ts', + './src/devtools/stub.ts', + ], exclude: ['src/__tests__'], srcDir: './src', tsconfigPath: 'tsconfig.prod.json', diff --git a/packages/angular-query-persist-client/package.json b/packages/angular-query-persist-client/package.json index ad231460b9..7a45aa5d95 100644 --- a/packages/angular-query-persist-client/package.json +++ b/packages/angular-query-persist-client/package.json @@ -26,8 +26,8 @@ "test:types:ts53": "node ../../node_modules/typescript53/lib/tsc.js --build", "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js --build", "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:ts56": "node ../../node_modules/typescript56/lib/tsc.js --build", + "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --build", "test:types:tscurrent": "tsc --build", "test:lib": "vitest", "test:lib:dev": "pnpm run test:lib --watch", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dc378b6c3d..f5f07e13e6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,7 +5,6 @@ settings: excludeLinksFromLockfile: false overrides: - '@tanstack/angular-query-devtools-experimental': workspace:* '@tanstack/angular-query-experimental': workspace:* '@tanstack/eslint-plugin-query': workspace:* '@tanstack/query-async-storage-persister': workspace:* @@ -305,9 +304,6 @@ importers: '@angular/router': specifier: ^20.0.0 version: 20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) - '@tanstack/angular-query-devtools-experimental': - specifier: workspace:* - version: link:../../../packages/angular-query-devtools-experimental '@tanstack/angular-query-experimental': specifier: workspace:* version: link:../../../packages/angular-query-experimental @@ -2276,31 +2272,6 @@ importers: specifier: ^2.2.8 version: 2.2.8(typescript@5.8.3) - packages/angular-query-devtools-experimental: - dependencies: - '@angular/common': - specifier: '>=16.0.0' - version: 19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) - '@tanstack/query-devtools': - specifier: workspace:* - version: link:../query-devtools - devDependencies: - '@angular/core': - specifier: ^20.0.0 - version: 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/platform-browser-dynamic': - specifier: ^20.0.0 - version: 20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/compiler@20.0.0)(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))) - '@tanstack/angular-query-experimental': - specifier: workspace:* - version: link:../angular-query-experimental - eslint-plugin-jsdoc: - specifier: ^50.5.0 - version: 50.5.0(eslint@9.15.0(jiti@2.4.2)) - npm-run-all2: - specifier: ^5.0.0 - version: 5.0.2 - packages/angular-query-experimental: dependencies: '@tanstack/query-core': @@ -2995,13 +2966,6 @@ packages: 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'} hasBin: true - '@angular/common@19.2.4': - resolution: {integrity: sha512-5iBerI1hkY8rAt0gZQgOlfzR69jj5j25JyfkDOhdZhezE0pqhDc69OnbkUM20LTau4bFRYOj015eiKWzE2DOzQ==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} - peerDependencies: - '@angular/core': 19.2.4 - rxjs: ^6.5.3 || ^7.4.0 - '@angular/common@20.0.0': resolution: {integrity: sha512-tZTvxDjx+wH74/hIpip63u4tlaXNVXkq1iVf4gk7RPQGCAYLNPDWma8X+RpXMXWikn4/mA5NS1VBBtStTbS+gg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -16531,13 +16495,6 @@ snapshots: transitivePeerDependencies: - chokidar - '@angular/animations@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))': - dependencies: - '@angular/common': 19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) - '@angular/core': 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0) - tslib: 2.8.1 - optional: true - '@angular/animations@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))': dependencies: '@angular/common': 20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) @@ -16621,12 +16578,6 @@ snapshots: - chokidar - supports-color - '@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)': - dependencies: - '@angular/core': 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0) - rxjs: 7.8.2 - tslib: 2.8.1 - '@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)': dependencies: '@angular/core': 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0) @@ -16669,14 +16620,6 @@ snapshots: rxjs: 7.8.2 tslib: 2.8.1 - '@angular/platform-browser-dynamic@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/compiler@20.0.0)(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))': - dependencies: - '@angular/common': 19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) - '@angular/compiler': 20.0.0 - '@angular/core': 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/platform-browser': 20.0.0(@angular/animations@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)) - tslib: 2.8.1 - '@angular/platform-browser-dynamic@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/compiler@20.0.0)(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))': dependencies: '@angular/common': 20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) @@ -16685,14 +16628,6 @@ snapshots: '@angular/platform-browser': 20.0.0(@angular/animations@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)) tslib: 2.8.1 - '@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))': - dependencies: - '@angular/common': 19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) - '@angular/core': 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0) - tslib: 2.8.1 - optionalDependencies: - '@angular/animations': 20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)) - '@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))': dependencies: '@angular/common': 20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) diff --git a/scripts/publish.js b/scripts/publish.js index 953763b569..a1ac340296 100644 --- a/scripts/publish.js +++ b/scripts/publish.js @@ -84,10 +84,6 @@ await publish({ name: '@tanstack/vue-query-devtools', packageDir: 'packages/vue-query-devtools', }, - { - name: '@tanstack/angular-query-devtools-experimental', - packageDir: 'packages/angular-query-devtools-experimental', - }, { name: '@tanstack/angular-query-experimental', packageDir: 'packages/angular-query-experimental',